2.2. المتغيرات والأنواع الأساسية

المتغير هو اسم تربطه بقيمة باستخدام عامل =. وبعد الإسناد، يمكن استخدام الاسم في أي مكان يمكن أن تُستخدم فيه القيمة:

width = 320
height = 240
pixels = width * height
print(pixels)               # prints 76800

يُقيَّم الطرف الأيمن من = أولًا، ثم تُربط النتيجة بالاسم الموجود على اليسار. وتؤدي قراءة اسم لم يُسنَد إليه قط إلى إطلاق NameError.

المتغير ما هو إلا تسمية. فهو يشير إلى قيمة -- والقيمة توجد في مكان آخر، ويمكن أن يكون للقيمة نفسها أي عدد من التسميات.

Three labels pointing at three boxed values; reassigning a label moves the arrow, not the value.

المتغيرات تسميات تشير إلى قيم. إعادة إسناد متغير تحرّك التسمية؛ ولا تغيّر القيمة التي كانت التسمية تشير إليها.

2.2.1. قواعد التسمية

  • تبدأ الأسماء بحرف أو شرطة سفلية، وقد تحتوي على حروف وأرقام وشرطات سفلية. frame_count و_internal صحيحان؛ أما 1st_frame فهو خطأ في بناء الجملة.

  • الأسماء حساسة لحالة الأحرف: Width وwidth متغيران مختلفان.

  • تجنّب إعادة استخدام الأسماء المدمجة مثل list أو str أو id() أو print() -- فحجبها لا يطلق خطأً، لكن المدمج الأصلي يصبح غير قابل للوصول لبقية البرنامج النصي.

  • العُرف المتّبع: snake_case للمتغيرات والدوال، وALL_CAPS للثوابت التي لا تنوي تغييرها، وCamelCase لأسماء الأصناف.

2.2.2. الأنواع الأساسية

لكل قيمة في Python نوع يحدد العمليات التي تدعمها. والأنواع الأربعة التي ستكتبها أكثر من غيرها هي:

  • int -- الأعداد الصحيحة، الموجبة أو السالبة. تنمو الأعداد الصحيحة في MicroPython بقدر ما تسمح الذاكرة. تُكتب القيم الحرفية كأرقام عادية: 0 و42 و-7. كما أن القيم الست عشرية (0x1A) والثمانية (0o17) والثنائية (0b1010) صحيحة أيضًا ومفيدة للسجلات وأقنعة البتات.

  • float -- الأعداد ذات الفاصلة العشرية أو الأُس: 3.14 و1.0 و-0.5 و2e6 (= 2,000,000.0). كل الأعداد العائمة على الكاميرا بصيغة IEEE 754 بطول 32 بت -- دقيقة إلى نحو سبعة أرقام معنوية.

  • bool -- إحدى القيمتين الحرفيتين True أو False (انتبه إلى حالة الأحرف).

  • str -- النص، يُكتب كأحرف بين علامتي اقتباس مفردتين أو مزدوجتين: "hello" و'OpenMV'. كلا أسلوبي الاقتباس متكافئان؛ اختر الأسلوب الذي يتيح لك تجنّب تهريب أحرف الاقتباس التي تظهر داخل السلسلة النصية.

هناك أيضًا قيمة خامسة جديرة بالمعرفة على الفور:

  • None -- القيمة الوحيدة من النوع NoneType. تُستخدم بمعنى "لا قيمة" أو "لم تُحدَّد بعد". الدوال التي لا تُرجع شيئًا صراحةً تُرجع None ضمنيًا.

2.2.3. فحص الأنواع وتحويلها

تُرجع الدالة المدمجة type() نوع أي قيمة:

>>> type(42)
<class 'int'>
>>> type(3.14)
<class 'float'>
>>> type("hello")
<class 'str'>

كل نوع يعمل أيضًا كدالة تحويل. مرّر إليها قيمة من نوع مختلف فتحصل على القيمة المكافئة بالنوع الجديد -- عندما يكون التحويل محدد المعالم:

>>> int("42")
42
>>> int(3.9)
3                           # truncates toward zero, not rounds
>>> float("1.5")
1.5
>>> str(255)
'255'
>>> bool(0), bool(1), bool("")
(False, True, False)

التحويلات غير محددة المعالم تطلق ValueError:

>>> int("hello")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid syntax for integer with base 10

2.2.4. إعادة الإسناد والتنميط الديناميكي

يمكن إعادة إسناد اسم إلى قيمة من أي نوع في أي وقت. ما يلي صحيح قانونيًا:

x = 42
x = "now I'm a string"
x = 3.14

لا يربط Python المتغير بنوع. الكود الذي يعتمد على كون x عددًا صحيحًا يتوقع ببساطة عددًا صحيحًا عند النقطة التي يستخدمه فيها؛ وإذا حصل على شيء آخر، فستحصل على TypeError أثناء التشغيل.

ملاحظة

إعادة إسناد x لا تغيّر القيمة التي كان الربط القديم يشير إليها. وإذا كان اسمان يتشاركان القيمة نفسها، فإن إعادة إسناد أحدهما لا تؤثر على الآخر:

a = [1, 2, 3]
b = a                       # both point at the same list
a = "different now"
print(b)                    # still [1, 2, 3]

أما تغيير قيمة مشتركة فهو أمر مختلف: فطريقة مثل list.append تغيّر القيمة التي يشير إليها الربط، فيرى كل اسم آخر يشير إلى القيمة نفسها هذا التغيير.