تنسيق المخرجات في بايثون

من موسوعة حسوب
اذهب إلى: تصفح، ابحث

تقدّم بايثون عددًا من الطرائق التي تساعد في تنسيق مخرجات البرامج، فيمكن طباعة البيانات بصيغة سهلة القراءة، أو يمكن كتابة البيانات في ملف لاستخدامه في المستقبل. 

استخدمنا في هذا التوثيق طريقتين لكتابة القيم: الأول هي العبارات expression statements والدالة print()‎. (هناك طريقة ثالثة وهي استخدام التابع write()‎ الخاص بالكائنات file، ويعرف ملف المخرجات القياسي بـ sys.stdout). 

تظهر الحاجة في كثير من الأحيان إلى التحكم في تنسيق المخرجات وإظهارها بأشكال مختلفة وليس كقيم مفصولة بفراغات وحسب. وهناك طريقتان لتنسيق المخرجات، الأولى هي القيام بعمليات معالجة السلاسل النصية يدويًّا، فباستخدام عمليتي اقتطاع السلاسل النصية (slicing) وربطها (concatenation) يمكن تنسيق المخرجات حسب الرغبة. وتمتلك السلاسل النصية بعض التوابع التي تؤدي بعض العمليات المفيدة التي ترتب السلاسل النصية في أعمدة ذات عرض محدد.

الطريقة الثانية هي استخدام حروف تنسيق السلاسل النصية أو التابع str.format()‎.

تضم وحدة string الصنف Template الذي يقدّم طرقًا أخرى لاستبدال القيم ضمن السلاسل النصية.

تقدم بايثون كذلك بعض الطرائق لتحويل القيم إلى سلاسل نصية، منها تمرير القيمة إلى إحدى الدالتين str()‎أو repr()‎.

تعيد الدالة str()‎ تمثيلًا للقيمة يكون قابلًا للقراءة، في حين تنشئ الدالة repr()‎ تمثيلًا يمكن لمفسّر بايثون أن يقرأه (أو تطلق الخطأ SyntaxError في حال عدم وجود صيغة مكافئة).

تعيد الدالة str()‎ نفس القيمة المعادة من الدالة repr()‎ إذا كان الكائن المراد تمثيله لا يملك صيغة خاصة يمكن قراءتها من قبل الإنسان، والأعداد والقوائم والقواميس هي خير مثال على هذه الكائنات. أما السلاسل النصية فتمتلك تمثيلين مختلفين، كما يوضح ذلك المثال التالي:
>>> s = 'Hello, world.'
>>> str(s)
'Hello, world.'
>>> repr(s)
"'Hello, world.'"
>>> str(1/7)
'0.14285714285714285'
>>> x = 10 * 3.25
>>> y = 200 * 200
>>> s = 'The value of x is ' + repr(x) + ', and y is ' + repr(y) + '...'
>>> print(s)
The value of x is 32.5, and y is 40000...
>>> # The repr() of a string adds string quotes and backslashes:
... hello = 'hello, world\n'
>>> hellos = repr(hello)
>>> print(hellos)
'hello, world\n'
>>> # يمكن لوسائط الدالة التالية أن تكون من أنواع مختلفة
... repr((x, y, ('spam', 'eggs')))
"(32.5, 40000, ('spam', 'eggs'))"
فيما يلي طريقتان لكتابة جدول يضم مربّعات ومكعّبات الأرقام (لاحظ استخدام end في نهاية الدالة print):
>>> for x in range(1, 11):
...     print(repr(x).rjust(2), repr(x*x).rjust(3), end=' ')
...     print(repr(x*x*x).rjust(4))
...
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000

>>> for x in range(1, 11):
...     print('{0:2d} {1:3d} {2:4d}'.format(x, x*x, x*x*x))
...
 1   1    1
 2   4    8
 3   9   27
 4  16   64
 5  25  125
 6  36  216
 7  49  343
 8  64  512
 9  81  729
10 100 1000
لاحظ إضافة مسافة بيضاء واحدة في المثال الأول بين كل عمود بواسطة الدالة print(). تضيف هذه الدالة المسافات البيضاء بين وسائطها بصورة افتراضية).

يوضح المثال السابق طريقة استخدام التابع str.rjust()‎ الخاص بكائنات السلاسل النصية، والذي يعمل على محاذاة السلسلة النصية في حقل ذي عرض محدّد إلى جهة اليمين وذلك بإضافة المسافات البيضاء إلى يسار السلسلة، وهناك تابعان آخران مماثلان هما str.ljust()‎ لمحاذاة السلاسل النصية إلى اليسار وstr.center()‎ لمحاذاتها وسطيًّا. 

لا تكتب هذه التوابع أيّ شيء، وإنّما تعيد سلسلة نصية جديدة، وإن كانت السلسلة النصية المدخلة طويلة جدًّا لن تقوم هذه التوابع بتقصير السلسلة النصية ممّا قد يخلّ بترتيب الأعمدة، وهو الخيار الأفضل مقارنة بتغيير القيمة الحقيقية. (إن كنت ترغب في تقصير السلاسل يمكن إضافة عامل الاقتطاع مثل: x.ljust(n)[:n]‎).

هناك تابع آخر هو str.zfill()‎ ووظيفته إزاحة السلاسل النصية المتكونة من أرقام إلى جهة اليسار باستخدام الأصفار، ويمكن لهذا التابع أن يتعامل مع الأعداد الموجبة والسالبة:
>>> '12'.zfill(5)
'00012'
>>> '-3.14'.zfill(7)
'-003.14'
>>> '3.14159265359'.zfill(5)
'3.14159265359'
يمكن استخدام التابع str.format()‎ بالطريقة التالية:
>>> print('We are the {} who say "{}!"'.format('knights', 'Ni'))
We are the knights who say "Ni!"
تستبدل الأقواس والأحرف التي بداخلها (والتي تدعى بحقول التنسيق) بالكائنات الممررة إلى التابع str.format()‎. ويمكن استخدام رقم داخل القوس للإشارة إلى موقع الكائن الممرّر في التابع str.format()‎:
>>> print('{0} and {1}'.format('spam', 'eggs'))
spam and eggs
>>> print('{1} and {0}'.format('spam', 'eggs'))
eggs and spam
يمكن أيضًا استخدام الوسائط المفتاحية (keyword arguments) في التابع str.format() ويمكن الإشارة إلى قيمها باستخدام اسم الوسيط:
>>> print('This {food} is {adjective}.'.format(
...       food='spam', adjective='absolutely horrible'))
This spam is absolutely horrible.
يمكن أيضًا استخدام الوسائط المفتاحية والموضعية في نفس الوقت وحسب الحاجة:
>>> print('The story of {0}, {1}, and {other}.'.format('Bill', 'Manfred', other='Georg'))
The story of Bill, Manfred, and Georg.
يمكن استخدام الوسيط ‎'!a'‎ (تطبيق الدالة ascii()) و ‎'!s'‎ (تطبيق الدالة str()‎) و ‎'!r'‎ (تطبيق الدالة repr()) لتحويل القيم قبل تنسيقها:
>>> contents = 'eels'
>>> print('My hovercraft is full of {}.'.format(contents))
My hovercraft is full of eels.
>>> print('My hovercraft is full of {!r}.'.format(contents))
My hovercraft is full of 'eels'.
يمكن استخدام الوسيط الاختياري ':' ومحدّد التنسيق (format specifier) بعد اسم الحقل، ويتيح هذه المزيد من التحكّم في القيمة المنسّقة. في المثال التالي تقرّب قيمة العدد Pi إلى ثلاث مراتب بعد الفاصلة العشرية:
>>> import math
>>> print('The value of PI is approximately {0:.3f}.'.format(math.pi))
The value of PI is approximately 3.142.
يؤدي تمرير عدد صحيح بعد الوسيط ':' إلى تغيير عرض الحقل إلى العدد المحدّد، ويساعد هذا الأمر في جعل الجداول أكثر ترتيبًا:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
...     print('{0:10} ==> {1:10d}'.format(name, phone))
...
Jack       ==>       4098
Dcab       ==>       7678
Sjoerd     ==>       4127
إن كانت السلسلة النصية طويلة ولا ترغب في تقطيعها، سيكون من الأفضل أن تشير إلى المتغير الذي ترغب في تنسيقه بواسطة اسمه لا بواسطة موقعه. يمكن القيام بذلك عن طريق تمرير القاموس واستخدام الأقواس المربعة '[]' للوصول إلى المفاتيح:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {0[Jack]:d}; Sjoerd: {0[Sjoerd]:d}; '
...       'Dcab: {0[Dcab]:d}'.format(table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678
يمكن القيام بذلك أيضًا عن طريق تمرير الجدول كوسيط مفتاحي مع إضافة الرمز '**':
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678}
>>> print('Jack: {Jack:d}; Sjoerd: {Sjoerd:d}; Dcab: {Dcab:d}'.format(**table))
Jack: 4098; Sjoerd: 4127; Dcab: 8637678
هذه الطريقة مفيدة للغاية مع الدالة الداخلية vars() والتي تعيد قاموسًا يحتوي على جميع المتغيرات المحلية.

طريق التنسيق القديمة

يمكن استخدام العامل % لتنسيق السلاسل النصية، إذ يفسّر هذا العامل الأيسر والذي يشبه سلسلة تنسيق نصية بنفس نمط sprintf()‎ في تنسيق السلاسل النصية وتطبيقها على الوسيط الأيمن، وإعادة السلسلة النصية الناتجة من عملية التنسيق هذه. يوضح المثال التالي طريقة عمل هذا العامل:
>>> import math
>>> print('The value of PI is approximately %5.3f.' % math.pi)
The value of PI is approximately 3.142.
يمكن الحصول على المزيد من المعلومات في قسم نمط printf لتنسيق السلاسل النصية.

مصادر