أنواع البيانات ودالة الفحص type()
رأينا حتى الآن أنواعًا متعددة من البيانات: النصوص، القوائم، الأعداد، والقيم المنطقية. تسمى هذه أنواعًا(types). كل قيمة لها نوع يؤثر في طريقة سلوكها، ويمكن معرفة النوع باستخدام الدالة type:
print(type('Hello World'))
print(type(23))
print(type(True))
print(type([1, 2, 3]))
print(type(4.56))
سيخبرك بايثون أولًا أن type('Hello World') هي <class 'str'>. لا تقلق بشأن كلمة class الآن؛ المهم أن str اختصار لـstring، أي نص.
بعد ذلك سترى أن True من النوع bool، اختصار boolean، وأن [1, 2, 3] من النوع list.
وللأعداد نوعان أساسيان هنا:
int، اختصار integer، للأعداد الصحيحة التي لا تحتوي على جزء عشري.float، اختصار floating point number، للأعداد التي تحتوي على نقطة عشرية وقد تحتوي على جزء كسري.
في معظم العمليات الحسابية لا تحتاج إلى القلق كثيرًا بشأن الفرق بينهما، لأن بايثون يسمح بخلط النوعين في الحسابات المعتادة.
والأنواع نفسها قيم يمكن استخدامها في تعبيرات. جرّب في الطرفية:
type(3) == int
القيم من أنواع مختلفة تكون عادة مختلفة فعلًا، لكنها قد تبدو متشابهة عند الطباعة، وهذا قد يسبب ارتباكًا. جرّب:
print('123')
print(123)
print(123 == '123')
يمكنك استخدام repr مثل print(repr(123)) وprint(repr('123')) لرؤية تمثيل يساعدك على التمييز بينهما.
الأنواع المختلفة تدعم دوال وعمليات مختلفة. بل إن العامل نفسه قد يعني شيئًا مختلفًا بحسب أنواع القيم.
انظر مثلًا كيف يختلف معنى + مع str عن معناه مع int:
print(123 + 456)
print('123' + '456')
بين عددين صحيحين يعمل + كعملية جمع، أما بين نصين فيعمل كدمج للنصوص. يحدد بايثون المعنى المناسب من أنواع القيم الداخلة.
وبالمثل يتصرف < بطريقة مختلفة مع نصين عن تصرفه مع عددين صحيحين:
print(13 < 120)
print('13' < '120')
مع الأعداد يعمل < بمعنى «أصغر من» المعتاد؛ مثلًا 13 أصغر من 120. أما مع النصوص فتكون المقارنة بحسب ترتيب الأحرف كما في الترتيب القاموسي. لذلك النص '13' يأتي بعد '120' لأن المقارنة النصية تصل إلى '3' مقابل '2'.
شاهد كيف يؤثر هذا الفرق عند ترتيب قائمة:
print(sorted([120, 13, 0]))
print(sorted(['120', '13', '0']))
ماذا يحدث إذا استخدمت عاملًا بين قيمة من النوع str وقيمة من النوع int؟ جرّب في الطرفية:
12 + '34'
اقرأ رسالة الخطأ؛ النوعان غير متوافقين مع هذه العملية مباشرة.
استخدام نص بدل عدد صحيح في range مثل range('5')، أو استخدام نص كفهرس قائمة مثل list['3']، يؤدي أيضًا إلى أخطاء.
يمكن حل كثير من هذه المشكلات بتحويل النوع. استخدام int كدالة يحول نصًا عدديًا إلى عدد صحيح: int('5') يعيد العدد 5. وبالعكس، str(5) يعيد النص '5'.
استخدم هذه المعرفة لإصلاح البرنامج المكسور:
number = '3'
for i in range(number):
print('Starting... ' + i + 1)
print('Go!')
يجب أن يطبع البرنامج الصحيح:
Starting... 1
Starting... 2
Starting... 3
Go!
ويجب أن يعمل لأي قيمة للمتغير number. ابحث عن المواضع التي تحتاج فيها إلى تحويل str إلى int أو int إلى str.
في أي مواضع هذا الكود معطّل؟
هناك قيم تحتاج إلى تحويل إلى نوع آخر.
تحديدًا يوجد
strيجب تحويله إلىint.ويوجد
intيجب تحويله إلىstr.
اكتب نسخة محسنة من format_board تضيف أرقام الصفوف والأعمدة بهذا الشكل:
123
1XOX
2 OO
3 X
يجب أن تعمل مع أي لوحة ذات حجم من رقم واحد. هذا اختبار جاهز:
def format_board(board):
...
check_result(
format_board([
['X', 'O', 'X'],
['O', ' ', ' '],
[' ', 'X', 'O']
]),
' 123\n1XOX\n2O \n3 XO'
)
السطر الأول يحتاج معاملة منفصلة: range يعطي 0 و1 و2... بينما المطلوب عرض 1 و2 و3... وتذكّر أن الأعداد يجب تحويلها إلى نصوص قبل دمجها. بعد ذلك ابنِ نص كل صف مع رقمه واجمع الأسطر باستخدام \n.
def format_board(board):
...
check_result(
format_board([
['X', 'O', 'X'],
['O', ' ', ' '],
[' ', 'X', 'O']
]),
' 123
1XOX
2O
3 XO'
)
يمكنك البدء بأفكار حلك السابق لـ
format_board. ويُنصح جدًا باستخدامjoin.يجب التعامل مع السطر الأول منفصلًا عن البقية.
تذكر أن
rangeتنتج الأعداد بهذا الشكل: 0، 1، 2، ...نريد في السطر الأول أرقامًا هكذا: 1، 2، 3...
يجب تحويل كل رقم إلى نص قبل إضافته إلى الصف الأول.
تعامل مع صفوف اللوحة بالطريقة نفسها تقريبًا.
ابدأ بقائمة تحتوي فقط على السطر الأول الذي أنشأته.
أضف نص كل صف إلى القائمة، ثم اجمع عناصر القائمة باستخدام محرف سطر جديد.
ممتاز!
وعندما تحتاج إلى دمج نصوص وأرقام، تذكّر أن بإمكانك استخدام f-strings أيضًا؛ فهي غالبًا أوضح من التحويل والدمج اليدوي.
أصبحت تعرف فكرة الأنواع في بايثون وكيف تتجنب أخطاء شائعة بتحويل القيم إلى النوع المناسب. واصل بناء بقية المشروع.