الانتقال إلى المحتوى الرئيسي
الوحدة 7 · الدرس 3 من 427/36 في الدورة~12 min
دروس الوحدة (3/4)

طرق خاصة (الدندر)

الطرق الخاصة (تسمى طرق dunder لأنها تبدأ وتنتهي بشرطة سفلية مزدوجة: __name__) هي الخطافات التي تسمح لكائناتك التكامل مع اللغة: تمثيل النص، المقارنة مع ==، دعم len()، in، والمشغلين، وما إلى ذلك.

لقد استخدمت بالفعل واحدًا: __init__.

__str__ و __repr__

إنهم يتحكمون في ما يظهر مع print() وفي REPL.

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

    def __repr__(self):
        return f"Punto({self.x}, {self.y})"

    def __str__(self):
        return f"({self.x}, {self.y})"

p = Punto(3, 4)
str(p)        # '(3, 4)'        — per umani
repr(p)       # 'Punto(3, 4)'   — per debugger / dev
print(p)      # '(3, 4)'
p             # Punto(3, 4)     in REPL → repr
[p, p]        # [Punto(3, 4), Punto(3, 4)]   — sempre repr nei contenitori

إذا قمت بتعريف __repr__ فقط، فستستخدمه Python أيضًا كبديل لـ محمي_INLINE_14.

__eq__: إعادة تعريف ==

افتراضيًا، يقوم a == b بمقارنة معرفات الكائنات (is)، وليس محتوياتها. للمقارنة الهيكلية، حدد __eq__:

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

    def __eq__(self, other):
        if not isinstance(other, Punto):
            return NotImplemented
        return (self.x, self.y) == (other.x, other.y)

Punto(1, 2) == Punto(1, 2)    # True
Punto(1, 2) == Punto(3, 4)    # False

إرجاع NotImplemented (كلمة رئيسية خاصة، وليس False!) عند الأنواع غير قابلة للمقارنة هي الممارسة الصحيحة: ستحاول بايثون بعد ذلك باستخدام ملف المعامل الآخر __eq__.

__len__: دعم len()

Python
class Cesto:
    def __init__(self):
        self.frutti = []

    def __len__(self):
        return len(self.frutti)

c = Cesto()
c.frutti.append("mela")
len(c)        # 1
bool(c)       # True (len > 0)

من خلال تعريف __len__، يمكنك أيضًا الحصول على منطقي مجانًا: كائن مع len() == 0 يصبح خطأ.

معلومات مفيدة أخرى (نظرة عامة)

  • __add__(self, other) → يعيد تعريف +
  • __lt__، __le__، __gt__، __ge__ → عوامل المقارنة
  • __contains__(self, item) → يدعم item in self
  • __iter__ + __next__ → يجعل الكائن قابلاً للتكرار
  • __getitem__(self, key) → يدعم self[key]
  • __hash__ → مطلوب ليكون مفتاح الإملاء / عنصر المجموعة

دورك

تمرين#python.m7.l3.e1
المحاولات: 0جارٍ التحميل…

حدد `Money` باستخدام __init__(self, المبلغ, العملة) و__str__ الذي يُرجع `f'{amount} {currency}'`. قم بإنشاء `s = Money(42, 'EUR')` وتقييم `str(s)`.

جارٍ تحميل المحرر…
إظهار التلميح

سلسلة f في __str__.

الحل متاح بعد 3 من المحاولات

تمرين المراجعة

تمرين#python.m7.l3.e2
المحاولات: 0جارٍ التحميل…

حدد "الزوج" مع __init__(self, a, b) و __eq__ بناءً على المقارنة الهيكلية لـ (a, b). تقييم `الزوج(1، 2) == الزوج(1، 2)'.

جارٍ تحميل المحرر…
إظهار التلميح

قارن بين الصفوف (self.a, self.b) == (other.a,other.b).

الحل متاح بعد 3 من المحاولات

التحدي الإضافي

تمرين#python.m7.l3.e3
المحاولات: 0جارٍ التحميل…

حدد فئة \`كتاب\` مع منشئ يأخذ \`العنوان\` و \`المؤلف\`. حدد الطريقة الخاصة \`__str__(self)\` بحيث تقوم بإرجاع السلسلة \`"العنوان حسب المؤلف"\` (على سبيل المثال \`'1984 بقلم جورج أورويل'\`). إنشاء مثيل لكتاب وتقييم \`str(book)\`.

جارٍ تحميل المحرر…
إظهار التلميح

استخدم f"{self.title} بواسطة {self.author}" داخل def __str__(self):.

الحل متاح بعد 3 من المحاولات