لدى لغة بايثون Python أسماء توابع خاصة تبدأ وتنتهي بشرطتين سفليتين وتختصر بالسحرية، وتسمى عادةً التوابع السحرية أو التوابع الخاصة أو توابع داندر Dunder Methods، أنت تعرف مسبقًا اسم التابع السحري __init__()
ولكن لدى بايثون العديد غيره، نستخدمهم عادةً لزيادة تحميل المعامل، أي إضافة سلوكيات خاصة تسمح لنا باستخدام كائنات الأصناف الخاصة بنا مع معاملات بايثون، مثل +
أو >=
. تسمح التوابع السحرية الأخرى لكائنات الأصناف الخاصة بنا بالعمل مع وظائف بايثون المضمنة مثل len()
و repe()
.
كما هي الحال في __init__()
أو توابع الجلب والضبط والحذف، لا نستدعي التوابع السحرية مباشرةً، يل تستدعيهم بايثون في الخلفية عندما تستخدم الكائنات مع المعاملات أو بعض الوظائف المضمنة. مثلًا، إذا أنشأت تابعًا اسمه __len__()
أو __repr__()
للأصناف الخاصة بك فستُستدعى في الخلفية عندما يمرر كائن من هذا الصنف إلى الدالة len()
أو repr()
على التوالي. هذه التوابع موثقة على الويب في توثيقات بايثون الرسمية.
سنحرص على التوسع في صنف WizCoin
أثناء استكشافنا لأنواع التوابع السحرية المختلفة وذلك لتحقيق أكبر استفادة ممكنة.
توابع تمثيل السلاسل النصية السحرية
يمكن استخدام التوابع السحرية __repr__()
و __str__()
لإنشاء سلسلة نصية تمثل كائنات لا تتعامل معها بايثون عادةً، إذ تُنشئ بايثون عادةً سلاسل تمثيل نصية للكائنات بطريقتين، سلسلة repr النصية وهي سلسلة نصية لشيفرة بايثون التي تُنشئ نسخة من الكائن عندما تُنفذ، وسلسلة str النصية التي هي سلسلة يستطيع الإنسان قراءتها وتؤمن معلومات واضحة ومفيدة عن الكائن. تعاد سلاسل repr و str عن طريق الدوال المبنية مسبقًا repr()
و str()
على التوالي. مثلًا، أدخل التالي إلى الصدفة التفاعلية لرؤية السلسلتين النصيتين repr و str للكائن datetime.date
:
>>> import datetime 1 >>> newyears = datetime.date(2021, 1, 1) >>> repr(newyears) 2 'datetime.date(2021, 1, 1)' >>> str(newyears) 3 '2021-01-01' 4 >>> newyears datetime.date(2021, 1, 1)
في هذا المثال، سلسلة repr -أي datetime.date(2021, 1, 1)
- للكائن datetime.date
(السطر 2) هي حرفيًا سلسلة نصية لشيفرة بايثون التي تُنشئ نسخةً من الكائن (السطر 1). تؤمن هذه النسخة تمثيلًا دقيقًا للكائن، ومن جهة أخرى، السلسلة النصية str -أي 2021-01-01
- للكائن datetime.date
(السطر 3) هي سلسلة نصية تمثل قيمة الكائن بطريقة سهلة القراءة للبشر. إذا أدخلنا ببساطة الكائن في الصدفة التفاعلية (السطر 4)، تظهِر السلسلة النصية repr. تظهر غالبًا السلسلة النصية str للمستخدمين وتُستخدم السلسلة النصية repr للكائن في السياق التقني مثل رسائل الخطأ والسجلات.
تعلم بايثون كيفية إظهار الكائنات في أنواعها المبنية مسبقًا مثل الأعداد الصحيحة والسلاسل النصية، ولكنها لا تعلم كيفية إظهار الكائنات للأصناف التي أنشأناها نحن. إذا لم يعرف repr()
كيفية إنشاء سلسلة نصية repr أو str لكائن، ستكون السلسلة النصية مغلفة بأقواس مثلثة وتحتوي عنوان الذاكرة واسم للكائن '<wizcoin.WizCoin object at 0x00000212B4148EE0>'
لإنشاء هذا النوع من السلاسل النصية لكائن WizCoin
أدخل التالي إلى الصدفة التفاعلية:
>>> import wizcoin >>> purse = wizcoin.WizCoin(2, 5, 10) >>> str(purse) '<wizcoin.WizCoin object at 0x00000212B4148EE0>' >>> repr(purse) '<wizcoin.WizCoin object at 0x00000212B4148EE0>' >>> purse <wizcoin.WizCoin object at 0x00000212B4148EE0>
لا تمتلك هذه السلاسل فائدة كبيرة وصعبة القراءة، لذا يمكننا إخبار بايثون ما نريد استخدامه عن طريق تطبيق التوابع السحرية __repr__()
و __str__()
؛ إذ يحدد التابع __repr__()
أي سلسلة نصية يجب أن تُعيدها بايثون عندما يمرر الكائن إلى الدالة المبنية مسبقًا repr()
؛ بينما يحدد التابع __str__()
أي سلسلة نصية يجب أن تُعيدها بايثون عندما يمرر الكائن إلى الدالة المبنية مسبقًا str()
. ضِف التالي إلى نهاية ملف wizcoin.py:
--snip-- def __repr__(self): """Returns a string of an expression that re-creates this object.""" return f'{self.__class__.__qualname__}({self.galleons}, {self.sickles}, {self.knuts})' def __str__(self): """Returns a human-readable string representation of this object.""" return f'{self.galleons}g, {self.sickles}s, {self.knuts}k'
عندما نمرر purse
إلى repr()
و str()
يستدعي بايثون التوابع السحرية __repr__()
و __str__()
، أي نحن لا نستدعي التوابع السحرية في الشيفرة الخاصة بنا.
لاحظ أن السلسة النصية f التي تضم الكائن في الأقواس تستدعي ضمنًا str()
للحصول على السلسة النصية str. مثلًا أدخل التالي إلى الصدفة التفاعلية:
>>> import wizcoin >>> purse = wizcoin.WizCoin(2, 5, 10) >>> repr(purse) # Calls WizCoin's __repr__() behind the scenes. 'WizCoin(2, 5, 10)' >>> str(purse) # Calls WizCoin's __str__() behind the scenes. '2g, 5s, 10k' >>> print(f'My purse contains {purse}.') # Calls WizCoin's __str__(). My purse contains 2g, 5s, 10k.
عندما نمرر الكائن WizCoin
في purse
إلى الدالتين repr()
و str()
، تستدعي بايثون في الخلفية التابعين __repr__()
و __str__()
الخاصين بالصنف WizCoin
. برمجنا هذين التابعين ليعيدا سلاسلًا نصيةً مفيدةً وسهلة القراءة. إذا أدخلت نص السلسلة النصية repr التالية 'WizCoin(2, 5, 10)'
إلى الصدفة التفاعلية ستُنشئ كائن WizCoin
لديه نفس سمات الكائن في purse
. السلسلة النصية str هي تمثيل أسهل للقراءة لقيمة الكائن 2g, 5s, 10k
. إذا استخدمت الكائن WizCoin
في السلسلة النصية f، ستستخدم بايثون السلسلة النصية str الخاصة بالكائن.
إذا كانت الكائنات WizCoin
معقدة لدرجة أنه من المستحيل إنشاء نسخة منها باستدعاء دالة بانية Constructor Function واحدة، نغلف السلسلة النصية repr في قوسين مثلثين للتنويه على أنه لا يمكن أن تصبح شيفرة بايثون. هكذا تكون سلسلة تمثيل نصي العامة، مثل '<wizcoin.WizCoin object at 0x00000212B4148EE0>'
. كتابة ذلك في الصَدَفة التفاعلية سيرفع خطأ SyntaxError
حتى لا يحدث ارتباك بشيفرة بايثون التي تُنشئ نسخة من ذلك الكائن.
نستخدم __self.__class__.__qualname
بدلًا من توفير السلسلة النصية WizCoin
في الشيفرة داخل التابع __repr__()
، إذ يستخدم التابع الموروث __repr__()
اسم الصنف الفرعي بدلًا من WizCoin
. إذا أعدنا تسمية الصنف WizCoin
سيستخدم التابع __repr__()
الاسم الجديد تلقائيًا. تظهِر السلسلة النصية str للكائن WizCoin
السمة بصورة أنيقة ومختصرة. يُفضّل جدًا تطبيق __repr__()
و __str__()
في كل الأصناف الخاصة بك.
المعلومات الحساسة في سلاسل REPR النصية
كما ذكرنا سابقًا، نظهر السلاسل النصية str للمستخدمين ونستعمل السلاسل النصية repr في سياق تقني مثل السجلات. ولكن يمكن أن تسبب السلاسل النصية repr مشاكل أمنية، إذا كان الكائن المُنشئ يحتوي على معلومات حساسة مثل كلمات المرور والتفاصيل الطبية والمعلومات الشخصية؛ ففي هذه الحالة تأكد من خلو التابع __repr__()
من هذه المعلومات في السلسلة النصية المرجعة، وعند تعطل البرنامج، يجري إعداده بصورة متكررة لتضمين محتويات المتغيرات في ملف السجل للمساعدة في تصحيح الأخطاء، ولا تُعامل عادةً ملفات الدخول هذه على أنها معلومات حساسة. تحتوي ملفات الدخول المفتوحة للعلن في العديد من الحوادث الأمنية كلمات المرور وأرقام بطاقات بنكية وعناوين المنازل ومعلومات حساسة أخرى، خذ ذلك بالحسبان عند كتابة التوابع __repr__()
الخاص بصنفك.
التوابع السحرية العددية Numeric Dunder Methods
تزيد التوابع السحرية العددية أو التوابع السحرية الرياضية من تحميل عامل بايثون الرياضية، مثل +
و -
و *
و /
وما شابه. لا نستطيع حاليًا تنفيذ عملية رياضية مثل جمع كائني WizCoin
باستخدام العامل +
، وإذا حاولنا فعل ذلك سترفع بايثون استثناء TypeError
لأنها لا تعرف كيفية إضافة كائنات WizCoin
. أدخل التالي إلى الصدفة التفاعلية لمشاهدة هذا الخطأ:
>>> import wizcoin >>> purse = wizcoin.WizCoin(2, 5, 10) >>> tipJar = wizcoin.WizCoin(0, 0, 37) >>> purse + tipJar Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'WizCoin' and 'WizCoin'
يمكنك استخدام التابع السحري ()__add__
بدلًا من كتابة التابع addWizCoin()
لصنف WizCoin
، لكي تعمل كائنات WizCoin
مع العامل +
. أضف التالي إلى نهاية ملف wizcoin.py:
--snip-- 1 def __add__(self, other): """Adds the coin amounts in two WizCoin objects together.""" 2 if not isinstance(other, WizCoin): return NotImplemented 3 return WizCoin(other.galleons + self.galleons, other.sickles + self.sickles, other.knuts + self.knuts)
تستدعي بايثون التابع ()__add__
عندما يكون الكائن WizCoin
على يسار المعامل +
وتمرر القيمة على الجانب الأيمن من المعامل +
للمعامل other
(يمكن تسمية المعامل أي شيء ولكن الاصطلاح هو other
).
تذكر أنه يمكن تمرير أي نوع من أنواع الكائنات إلى التابع ()__add__
، لذا يجب على التابع أن يحتوي اختبارات من النوع، فمثلًا ليس من المنطقي إضافة رقم عشري أو عدد صحيح إلى كائن WizCoin
لأننا لا نعرف إذا كان يجب إضافته إلى galleons
أو sickles
أو knuts
.
يُنشئ التابع ()__add__
كائن WizCoin
جديد مع كميات تساوي مجموع السمات galleons
و sickles
و knuts
من self
و other
3 لأن هذه السمات الثلاث تحتوي الأعداد الصحيحة التي يمكننا استخدام المعامل +
عليهم. الآن بعد أن حمّلنا العامل +
لصنف WizCoin
، يمكننا استخدام العامل +
على الكائن WizCoin
.
يسمح لنا زيادة تحميل العامل +
بكتابة شيفرة أكثر قابليّة للقراءة. مثلًا، أدخل التالي إلى الصدفة التفاعلية:
>>> import wizcoin >>> purse = wizcoin.WizCoin(2, 5, 10) # إنشاء كائن WizCoin >>> tipJar = wizcoin.WizCoin(0, 0, 37) # إنشاء كائن WizCoin آخر >>> purse + tipJar # إنشاء كائن WizCoin آخر يحتوي على المجموع WizCoin(2, 5, 47)
إذا مُرر نوع الكائن الخطأ إلى other
، لن يرفع التابع السحري استثناءً ولكنه سيعيد القيمة المبنية مسبقًا NotImplemented
، فمثلًا، other
في الشيفرة التالية هي عدد صحيح:
>>> import wizcoin >>> purse = wizcoin.WizCoin(2, 5, 10) >>> purse + 42 # لا يمكن إضافة كائنات WizCoin مع الأعداد الصحيحة Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unsupported operand type(s) for +: 'WizCoin' and 'int'
تشير إعادة NotImplemented
إلى بايثون لاستدعاء التوابع لتؤدي هذه العملية. سنتوسع حول "التوابع السحرية العددية المعكوسة" بتفصيل أكثر في هذا المقال. تستدعي بايثون في الخلفية التابع ()__add__
مع 42
للمعامل other
الذي يعيد NotImplemented
مما يؤدي لأن ترفع بايثون TypeError
.
على الرغم من أنه لا يجب إضافة الأعداد الصحيحة أو طرحهم من الكائن WizCoin
إلا أنه من المنطقي السماح للشيفرة بضرب كائنات WizCoin
بأعداد صحيحة موجبة عن طريق تعريف تابع سحري ()__mul__
. ضِف التالي في نهاية الملف wizcoin.py:
--snip-- def __mul__(self, other): """Multiplies the coin amounts by a non-negative integer.""" if not isinstance(other, int): return NotImplemented if other < 0: # Multiplying by a negative int results in negative # amounts of coins, which is invalid. raise WizCoinException('cannot multiply with negative integers') return WizCoin(self.galleons * other, self.sickles * other, self.knuts * other)
يسمح لك التابع ()__mul__
بضرب كائنات WizCoin
بأعداد صحيحة موجبة. إذا كان other
عدد صحيح، فهذا يعني أنه نوع البيانات التي يتوقعه التابع ()__mul__
ولا يجب أن نعيد NotImplemented
. ولكن إذا كان العدد الصحيح سالبًا، هذا يعني أن ضربه الكائن WizCoin
سيعطي قيم سلبية للنقود في الكائن WizCoin
لأن هذا يتعارض مع تصميمنا للصنف، نرفع WizCoinException
مع رسالة خطأ مفصلة.
ملاحظة: لا يجب تغيير الكائن self
في التابع السحري العددي، بل يجب على التابع إنشاء وإعادة كائن جديد بدلًا من ذلك، إذ يُتوقع من العامل +
ومن باقي العوامل أيضًا تقييم كائن جديد بدلًا من تعديل قيمة الكائن الموضعي.
أدخل التالي في الصدفة التفاعلية لمشاهدة عمل التابع السحري ()__mul__
:
>>> import wizcoin >>> purse = wizcoin.WizCoin(2, 5, 10) # إنشاء كائن WizCoin >>> purse * 10 # اضرب كائن WizCoin بعدد صحيح WizCoin(20, 50, 100) >>> purse * -2 # الضرب بعدد صحيح سالب يتسبب بخطأ Traceback (most recent call last): File "<stdin>", line 1, in <module> File "C:\Users\Al\Desktop\wizcoin.py", line 86, in __mul__ raise WizCoinException('cannot multiply with negative integers') wizcoin.WizCoinException: cannot multiply with negative integers
يظهر الجدول 1 قائمة التوابع السحرية العددية، لا توجد حاجة لتنفيذ كل التوابع في الصنف الخاص بك. حدد التوابع التي تفيدك.
التابع السحري | العملية | المعامل أو الدالة المضمنة |
---|---|---|
()__add__
|
جمع |
+
|
()__sub__
|
طرح |
-
|
()__mul__
|
ضرب |
*
|
()__matmul__
|
ضرب المصفوفات (جديد في بايثون 3.5) |
@
|
()__truediv__
|
قسمة |
/
|
()__floordiv__
|
قسمة عدد صحيح |
//
|
()__mod__
|
نسبة |
%
|
()__divmod__
|
قسمة ونسبة |
divmode()
|
()__pow__
|
رفع للأس |
** , pow
|
()__lshift__
|
انتقال لليسار |
>>
|
()__rshift__
|
انتقال لليمين |
<<
|
()__and__
|
عملية ثنائية و |
&
|
()__or__
|
عملية ثنائية أو |
|
|
()__xor__
|
عملية ثنائية أو حصرية |
^
|
()__neg__
|
سلبي |
أحادي - كما في -42
|
()__pos__
|
هوية |
أحادي + كما في +42
|
()__abs__
|
قيمة مطلقة |
()abs
|
()__invert__
|
عملية ثنائية عكس |
~
|
()__complex__
|
شكل العدد العقدي |
complex()
|
()__int__
|
شكل العدد الصحيح |
int()
|
()__float__
|
شكل العدد العشري |
float()
|
()__bool__
|
شكل بولياني |
bool()
|
()__round__
|
التدوير |
round()
|
()__trunc__
|
الاختصار |
math.trunc()
|
()__floor__
|
التدوير للأسفل |
math.floor()
|
()__ceil__
|
التدوير للأعلى |
math.ceil()
|
الجدول 1: التوابع السحرية العددية
بعض هذه التوابع مهمة لصنف WizCoin
، حاول كتابة التطبيق الخاص بك لكل من التوابع ()__sub__
و ()__pow__
و ()__int__
و ()__float__
و ()__bool__
. يمكنك مشاهدة أمثلة عن التطبيقات من خلال الرابط https://autbor.com/wizcoinfull. التوثيق الكامل للتوابع السحرية العددية موجود في توثيقات بايثون على الرابط https://docs.python.org/3/reference/datamodel.html#emulating-numeric-types.
تسمح التوابع السحرية العددية للكائنات الخاصة بأصنافك استخدام العوامل الرياضية الخاصة ببايثون. استخدم التوابع السحرية العددية في حال كتبت توابع تصف مهمة تابع موجود سابقًا أو دالة مبنية مسبقًا، مثل التابعين multiplyBy()
أو convertToInt()
أو ما شابه، إضافةً إلى التوابع السحرية المعكوسة أو الموضعية المشروحة في الفقرتين التاليتين.
التوابع السحرية العددية المعكوسة
تستدعي بايثون التوابع السحرية العددية عندما يكون الكائن على يسار العامل الرياضي، ولكنها تستدعي التابع السحري العددي المعكوس (يسمى أيضًا التابع السحري العددي العكوس أو اليد اليمين) عندما يكون الكائن على الطرف اليمين من العامل الرياضي.
التوابع السحرية العددية المعكوسة مفيدة لأن المبرمجين الذين يستخدمون الأصناف الخاصة بك لا يكتبون دومًا الكائن على الطرف اليسار من العامل الذي يقود بدوره لسلوك غير متوقع. لنرى مثلًا ما سيحدث عندما تحتوي purse
كائن WizCoin
وتعطي بايثون القيمة للتعبير 2 * purse
حيث purse
هي على الطرف اليمين للمعامل.
-
يُستدعى التابع
()__mul__
للصنفint
لأن2
هو عدد صحيح، وذلك مع تمريرpurse
للمعاملother
. -
لا يعرف التابع
()__mul__
للصنفint
كيف يتعامل مع الكائناتWizCoin
لذا يُعيدNotImplemented
. -
لا ترفع بايثون الخطأ
TypeError
الآن لأنpurse
تحتوي كائنWizCoin
، ويُستدعى التابع()__rmul__
الخاص بالصنفWizCoin
باستخدام2
ويُمرر إلى المعاملother
. -
ترفع بايثون الخطأ
TypeError
إذا أعاد التابع__rmul__()
القيمةNotImplemented
.
ما عدا ذلك تكون القيمة المعادة من ()__rmul__
هي نتيجة التعبير 2 * purse
.
يعمل التعبيرpurse * 2
بصورة مختلفة عندما تكون purse
على الجانب الأيسر من المعامل:
-
لأن
purse
تحتوي كائنWizCoin
، إذ يُستدعى تابع()__mul__
الخاص بالصنفWizCoin
ويمرر2
للمعاملother
. -
ينشئ التابع
()__mul__
كائنWizCoin
جديد ويعيده. -
الكائن المُعاد هو قيمة التعبير
purse * 2
.
لدى التوابع السحرية العددية والتوابع السحرية العددية المعكوسة نفس الشيفرة إذا كانت متبادلة. العوامل المتبادلة مثل الجمع لديها نفس النتيجة بالاتجاهين، 3+2
هي نفس 2+3
، ولكن المعاملات الأخرى ليست تبادلية فمثلًا 3-2
ليست 2-3
. أي عملية تبادلية يمكنها استدعاء نفس التابع السحري العددي الأساسي عندما يُستدعى التابع السحري العددي المعكوس؛ فمثلًا، أضف التالي في نهاية ملف wizcoin.py لتعريف التابع السحري العددي المعكوس لعامل الضرب:
--snip-- def __rmul__(self, other): """Multiplies the coin amounts by a non-negative integer.""" return self.__mul__(other)
ضرب عدد صحيح بكائن WizCoin
هو تبادلي، إذ أن 2 * purse
هي نفس purse * 2
. بدلًا من نسخ ولصق الشيفرة من ()__mul__
نستدعي فقط self.__mul__()
ونمررها للمعامل other
.
بعد تحديث mizcoin.py، جرب استخدام تابع الضرب السحري المعكوس عن طريق إدخال التالي إلى الصدفة التفاعلية:
>>> import wizcoin >>> purse = wizcoin.WizCoin(2, 5, 10) >>> purse * 10 # يستدعي __mul__() بقيمة 10 للمعامل other WizCoin(20, 50, 100) >>> 10 * purse # يستدعي __rmul__() بقيمة 10 للمعامل other WizCoin(20, 50, 100)
تذكر أن بايثون تستدعي في التعبير 10 * purse
تابع ()__mul__
الخاص بالصنف int
لمعرفة ما إذا كان بإمكان العدد الصحيح أن يُضرب بكائنات WizCoin
. لا يعلم طبعًا صنف بايثون int
المبني مسبقًا أي شيء عن الأصناف التي أنشأناها، لذا تعيد NotImplemented
. هذا يشير لبايثون باستدعاء التابع ()__rmul__
الخاص بصنف WizCoin
، وإذا كان موجودًا للتعامل مع العملية الحسابية،ترفع بايثون استثناء TypeError
إذا كان الاستدعائين للتابعين ()__mul__
و ()__rmul__
للصنفين Int
و WizCoin
على التتالي يعيدان NotImplemented
.
يمكن إضافة كائنات WizCoin
إلى بعضها فقط، وهذا يضمن أن التابع الأول ()__add__
الخاص بالصنف WizCoin
سيتعامل مع المعامل لذا لا نحتاج لتنفيذ ()__radd__
. مثلًا، في التعبير purse + tipJar
يُستدعى التابع ()__add__
للكائن purse
وتمرّر tipJar
للمعامل other
. لا تحاول بايثون استدعاء تابع ()__radd__
الخاص بالكائن tipJar
لأن هذا الاستدعاء لن يعيد NotImplemented
، وتكون purse
هي المعامل other
.
يحتوي الجدول 2 على قائمة كاملة للتوابع السحرية العددية المعكوسة.
التابع السحري | العملية | المعامل أو الدالة المضمنة |
---|---|---|
()__radd__
|
جمع |
+
|
()__rsub__
|
طرح |
-
|
()__rmul__
|
ضرب |
*
|
()__rmatmul__
|
ضرب المصفوفات (جديد في بايثون 3.5) |
@
|
()__rtruediv__
|
قسمة |
/
|
()__rfloordiv__
|
قسمة عدد صحيح |
//
|
()__rmod__
|
نسبة |
%
|
()__rdivmod__
|
قسمة ونسبة |
divmode()
|
()__rpow__
|
رفع للأس |
pow , **
|
()__rlshift__
|
انتقال لليسار |
<<
|
()__rrshift__
|
انتقال لليمين |
>>
|
()__rand__
|
عملية ثنائية و |
&
|
()__ror__
|
عملية ثنائية أو |
|
|
()__rxor__
|
عملية ثنائية أو حصرية |
^
|
الجدول 2: التوابع السحرية العددية المعكوسة
التوثيق الكامل للتوابع السحرية المعكوسة موجود في توثيقات بايثون.
الخلاصة
تسمح لك بايثون بإعادة تعريف العوامل باستخدام التوابع السحرية التي تبدأ وتنتهي بمحرفي شرطة سفلية، كما يمكن إعادة صياغة العوامل الرياضية الشائعة باستخدام التوابع السحرية العددية والمعكوسة، إذ تقدم هذه التوابع طريقة لعمل عوامل بايثون الموضعية مع كائنات الأصناف التي أنشأتها وإذا لم تكن قادرة على التعامل مع نوع بيانات الكائن على الطرف الأخر من المعامل ستعيد قيمة NotImplemented
المبنية مسبقًا. تُنشئ هذه التوابع السحرية وتعيد كائنات جديدة، في حين تُعدل التوابع السحرية الموضعية (التي تُعيد تعريف معاملات الإسناد المدعومة) الكائنات موضعيًا. لا تنفذ التوابع السحرية المقارنة معاملات بايثون الستة للمقارنة فقط، ولكن تسمح لدالة بايثون sort()
بترتيب كائنات الأصناف الخاصة بك. ستحتاج لاستخدام الدوال eq()
و ne()
و lt()
و le()
و gt()
و ge()
في وحدة العامل لمساعدتك في تنفيذ هذه التوابع السحرية.
تسمح الخواص والتوابع السحرية بكتابة الأصناف الخاصة بك بطريقة متناسقة وقابلة للقراءة، كما تسمح لك بتفادي الشيفرة النمطية التي تتطلبها لغات البرمجة الأخرى مثل جافا. لتعلم كتابة شيفرة بايثون هناك حديثان لريموند هيتغير Raymond Hettiger يتوسعان في هذه الأفكار "تحويل الشيفرة إلى بايثون اصطلاحية". و"ما وراء PEP 8 - أفضل الممارسات لشيفرة جميلة وواضحة" التي تغطي بعض المفاهيم التي ذكرناها وأكثر.
ترجمة -وبتصرف- لقسم من الفصل Pythonic OOP: Properities and dunder methods من كتاب Beyond the Basic Stuff with Python.
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.