2.20. الأصناف

إن الصنف يجمع البيانات والدوال التي تعمل على تلك البيانات تحت اسم واحد. واللجوء إليه يكون جديراً عندما تنتمي عدة قطع من الحالة معاً وتأخذ معظم الدوال في برنامج نصي المجموعة نفسها من القيم كوسائط.

2.20.1. الكلمة المفتاحية class

الكلمة المفتاحية هي class. يحوي الجسم تابع __init__ يُشغَّل في كل مرة تُنشأ فيها نسخة جديدة:

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

p = Point(3, 4)
print(p.x, p.y)

المخرجات:

3 4

إن Point هو الصنف؛ و p هي نسخة منه. تستدعي الأقواس في النداء Point(3, 4) التابع __init__، الذي يُسنِد الوسائط إلى سمات على النسخة الجديدة. و self هو الاسم الاصطلاحي للنسخة؛ و self.x يضبط سمة ستقرؤها بقية توابع النسخة.

2.20.2. متى تستخدم صنفاً

الجأ إلى صنف عندما تكون هذه الأمور صحيحة في الوقت نفسه:

  • حفنة من القيم المترابطة تسافر معاً في كل مكان (إحداثيا نقطة x و y؛ قيمة قراءة مستشعر ووحدتها وطابعها الزمني).

  • عدة دوال تأخذ المجموعة نفسها من القيم وتعمل عليها.

  • من المفيد إبقاء أكثر من حزمة من هذه الحزم حيّة في الوقت ذاته، متمايزة بعضها عن بعض.

إذا كانت البيانات لمرة واحدة، فإن dict أو tuple عادية تكون عادةً كافية. وإذا كنت تحتاج فقط إلى حزمة واحدة من الثوابت، فإن المتغيرات على مستوى الوحدة مناسبة. إن الأصناف ليست الحاوية الافتراضية -- بل تكتسب مكانتها عندما تريد الحالة والسلوك أن يلتصقا معاً.

2.20.3. ما الذي يفعله __init__

إن __init__ ما هو إلا تابع عادي. وكل ما يُسنَد إلى self داخله يصبح سمة على النسخة الجديدة:

class Sensor:
    def __init__(self, name, unit):
        self.name = name
        self.unit = unit
        self.readings = []

temp = Sensor("temperature", "C")
print(temp.name, temp.unit, temp.readings)

المخرجات:

temperature C []

تُهيّأ readings إلى قائمة فارغة -- فتحصل كل نسخة جديدة على قائمتها الخاصة، لا قائمة مشتركة. وأي شيء لا يُسنَد إلى self يكون محلياً ضمن __init__ ويختفي عند عودته.