Python/formatting output

من موسوعة حسوب
< Python
مراجعة 04:23، 22 مارس 2018 بواسطة Mohammed Taher (نقاش | مساهمات) (أنشأ الصفحة ب'تقدّم بايثون عددًا من الطرق التي تساعد في تنسيق مخرجات البرامج، فيمكن طباعة البيانات بصيغة س...')
(فرق) → مراجعة أقدم | المراجعة الحالية (فرق) | مراجعة أحدث ← (فرق)
اذهب إلى التنقل اذهب إلى البحث

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

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

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

الطريقة الثانية هي استخدام حروف تنسيق السلاسل النصية أو التابع 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]‎).

هناك تابع آخر هو st.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()‎ والتي تعيد قاموسًا يحتوي على جميع المتغيرات المحلية. 

للاطلاع بصورة أوسع على تنسيق السلاسل النصية باستخدام التابع str.format()‎ راجع قسم صيغة تنسيق السلاسل النصية.

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

يمكن استخدام العامل % لتنسيق السلاسل النصية، إذ يفسّر هذا العامل الأيسر والذي يشبه سلسلة تنسيق نصية بنفس نمط السلاسل المستخدمة في sprintf()‎ وتطبيقها على الوسيط الأيمن، وإعادة السلسلة النصية الناتجة من عملية التنسيق هذه. يوضح المثال التالي طريقة عمل هذا العامل:

>>> import math
>>> print('The value of PI is approximately %5.3f.' % math.pi)
The value of PI is approximately 3.142.

يمكن الحصول على المزيد من المعلومات في قسم نمط printf لتنسيق السلاسل النصية.

مصادر

صفحة Input and Output في توثيق بايثون الرسمي.