الدالة functools.total_ordering()‎ في بايثون

من موسوعة حسوب

يقوم مُزخرف الأصناف functools.total_ordering()‎ بزخرفة صنف يُعرّف تابعًا أو عدّة توابع ترتيب مُقارنة غنيّة (rich comparison ordering methods)، ويقوم بإضافة بقيّة توابع المُقارنة. يُبسّط هذا الجهد المبذول في تحديد جميع عمليّات المُقارنة الغنيّة المُمكنة.

يجب على الصّنف أن يُعرّف التّابع الخاصّ ‎__lt__()‎، أو ‎__le__()‎، أو ‎__gt__()‎، أو ‎__ge__()‎. إضافة إلى التّابع الخاصّ ‎__eq__()‎.

البنية العامة

@functools.total_ordering

المعاملات

لا توجد مُعاملات.

أمثلة

المثال التّالي يوضّح كيفيّة استعمال المُزخرف للمُقارنة بين سياراتٍ حسب سُرعتها، تابع حالة التّساوي يُشير إلى أنّ نُسخةً من السّيارة تُساوي نُسخةً أخرى إن كانت سُرعتهما مُتساويّة، وتابع حالة "أصغر من" يُشير إلى أنّ السّيارة أصغر من أخرى إن كانت سُرعتها أصغر.

ورغم أنّنا لم نُعرّف سوى تابع حالة "أصغر من" إلّا أنّ المُزخرف قد أضاف توابع المُقارنة الأخرى، وبالتّالي يُمكننا المُقارنة بين السّيارات بالطرقٌ الأخرى:

@functools.total_ordering
class Car:
    def __init__(self, name, speed):
        self.name = name
        self.speed = speed

    def __eq__(self, other_car):
        """ في حالة التّساوي """
        return self.speed == other_car.speed

    def __lt__(self, other_car):
        """ في حالة أصغر من """
        return self.speed < other_car.speed


>>> toyota = Car(name="Toyota", speed=220)
>>> tesla = Car(name="Tesla", speed=300)
>>> ford = Car(name="Ford", speed=220)
>>> 
>>> toyota == ford
True
>>> toyota == tesla
False
>>> toyota <= tesla
True
>>> toyota < tesla
True
>>> toyota > tesla
False
>>> tesla > ford
True

لو لم نستعمل المُزخرف لما كانت كلّ المُقارنات أعلاه مُمكنة:

>>> class Car:
...     def __init__(self, name, speed):
...         self.name = name
...         self.speed = speed
...     
...     def __eq__(self, other_car):
...         return self.speed == other_car.speed
...     
...     def __lt__(self, other_car):
...         return self.speed < other_car.speed
... 
>>> toyota = Car(name="Toyota", speed=220)
>>> tesla = Car(name="Tesla", speed=300)
>>> toyota < tesla
True

>>> toyota >= tesla
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    toyota >= tesla
TypeError: '>=' not supported between instances of 'Car' and 'Car'

وهذا مثال على كيفيّة استعمال المُزخرف للمقارنة بين أسماء طلّابٍ وأنسابهم:

@total_ordering
class Student:
    def _is_valid_operand(self, other):
        return (hasattr(other, "lastname") and
                hasattr(other, "firstname"))
    def __eq__(self, other):
        if not self._is_valid_operand(other):
            return NotImplemented
        return ((self.lastname.lower(), self.firstname.lower()) ==
                (other.lastname.lower(), other.firstname.lower()))
    def __lt__(self, other):
        if not self._is_valid_operand(other):
            return NotImplemented
        return ((self.lastname.lower(), self.firstname.lower()) <
                (other.lastname.lower(), other.firstname.lower()))

ملاحظات

يُسهّل المُزخرف functools.total_ordering()‎ من مُهمّة إنشاء أنواع يُمكن المُقارنة بينها بشكل كامل، لكنّ هذا التّسهيل يأتي بضريبة تنفيذ أبطأ وتعقيد أكثرًا في تتبّعات التّكدّس (stack traces) لتوابع المُقارنة المأخوذة. إن كانت اختبارات الأداء تُشير إلى أنّ هذا المُزخرف يُشكّل عائقًا لأداء تطبيقٍ مُعيّن، فكتابة توابع المُقارنة السّتّة جميعها سيُوفّر في الغالب تحسينًا في سرعة التّنفيذ.

انظر أيضًا

مصادر