AzLearn

أساليب dunder الخاصة

Special (Dunder) Methods

مفهوم ~22 دقيقة

أساليب dunder الخاصة — Special (Dunder) Methods

عندما تكتب len([1, 2, 3]) أو "a" + "b" أو print(obj) — Python في الحقيقة تستدعي أساليب خاصة في الخلفية. هذه الأساليب تُسمى dunder methods (اختصار Double Underscore) لأن اسمها يبدأ وينتهي بشرطتين سفليتين مزدوجتين: __str__, __add__, __eq__.

يمكنك تعريف هذه الأساليب في كلاساتك لتجعل كائناتك تستجيب لعمليات Python القياسية مثل الطباعة والمقارنة والجمع والتكرار.

لماذا dunder Methods؟

nums = [10, 20, 30]
print(len(nums))   # يستدعي nums.__len__()
print(nums[0])     # يستدعي nums.__getitem__(0)
nums2 = nums + [40]  # يستدعي nums.__add__([40])

عندما تكتب كلاساً خاصاً بك وتريد أن يتصرف بشكل طبيعي مع هذه العمليات، تحتاج لتطبيق الأساليب المقابلة.

__str__ و__repr__

الفرق: __str__ للعرض للمستخدم، __repr__ للمطوّر والتصحيح.

main.go

متى تستخدم أيهما؟

  • __str__: لما يظهر للمستخدم — رسالة واضحة وجميلة.
  • __repr__: لما تريده في السجلات والتصحيح — دقيق ومحدد، يُفضَّل أن يكون valid Python يمكن تنفيذه لإعادة إنشاء الكائن.
  • إذا لم تُعرّف __str__، يرجع Python لـ__repr__. لذا ابدأ دائماً بـ__repr__ إذا كانت الأولوية للتصحيح.

__eq__ — المقارنة بالمساواة

بدون __eq__، مقارنة كائنين دائماً False حتى لو حقولهما متطابقة (لأن Python يقارن الهوية في الذاكرة لا القيمة).

main.go

NotImplemented (ليس None) قيمة خاصة تخبر Python أن هذه الكلاس لا تعرف كيف تقارن بالنوع الآخر، فيحاول Python الجهة الأخرى.

__len__ — طول الكائن

main.go

بمجرد تعريف __len__، يعمل bool() تلقائياً: الكائن True إذا كان طوله أكبر من صفر، وFalse إذا كان صفراً.

__add__ — عامل الجمع

main.go

__rmul__ يُستدعى عندما Python لا يعرف كيف يُنجز 3 * v1 من جهة العدد — يجرب الجانب الأيمن بدلاً من ذلك.

__iter__ — جعل الكائن قابلاً للتكرار

main.go

yield داخل __iter__ يُحوّله إلى generator تلقائياً — أبسط من كتابة __iter__ و__next__ منفصلَين.

جمع dunder Methods في كلاس واحد

main.go

جدول مرجعي سريع

أسلوب dunderمتى يُستدعىمثال
__str__print(obj), str(obj)عرض لطيف للمستخدم
__repr__repr(obj), في القوائمتمثيل تقني دقيق
__eq__obj1 == obj2مقارنة بالقيمة
__len__len(obj), bool(obj)حجم/طول الكائن
__add__obj1 + obj2عملية الجمع
__mul__obj * nعملية الضرب
__iter__for x in obj, list(obj)التكرار
__contains__item in objاختبار الاحتواء
__getitem__obj[key]الفهرسة
تحدي — Challenge