الوحدة operator‎ في بايثون

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

تُقدّم الوحدة operator مجموعة من الدوال الفعالّة سرعةً وأداءً، والتي تُماثل العوامل الأساسيّة في بايثون.

على سبيل المثال، الاستدعاء ‎operator.add(x, y)‎ يُماثل التّعبير x+y. العديد من أسماء الدوال هنا هي نفسها المُستعمَلة في التوابع الخاصّة (special methods)، مع إزالة الشرطتين التحتيتين (‎add()‎ عوضًا عن ‎__‎‎add‎__‎()‎). ولإبقاء التوافقيّة العكسيّة مع نسخ أقدم من بايثون، فالكثير من الدوال تمتلك دوالًا مُكافئةً لها تُبقي على الشرطتين. ومن المُفضّل استخدام أسماء الدوال عديمة الشرطتين لتكون الشيفرة أوضحَ وأسهل قراءةً، أي أنّه من المُفضّل استعمال الدّالة ‎add()‎ عوضًا عن الدالة ‎__‎‎add‎__‎()‎، ولو كان لهما نفس التأثير.

تندرج هذه الدوال تحت الأقسام التّالية:

  • المقارنة بين الكائنات.
  • العمليات المنطقيّة.
  • العمليات الرياضيّة.
  • عمليّات التّسلسلات.

دوال المقارنة بين الكائنات مُفيدة لاستعمالها مع جميع الكائنات للمقارنة بينها، وقد سُميَّت بأسماء عوامل المقارنة الغنيّة (rich comparison operators).

operator.lt(a, b)‎‎

operator.‎__lt__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a < b‎.

operator.le(a, b)‎‎

operator.‎__le__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a <= b‎.

operator.eq(a, b)‎‎

operator.‎__eq__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a == b‎.

operator.ne(a, b)‎‎

operator.‎__ne__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a != b‎.

operator.ge(a, b)‎‎

operator.‎__ge__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a >= b‎.

operator.gt(a, b)‎‎

operator.‎__gt__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a > b‎.

تُقارن هذه الدوال بين القيمة a والقيمة b، لكن لاحظ أنّها قد تُعيد أيّ نوع من القيم، يُمكن للقيمة المُعادة أن تكون أو لا تكون قابلةً للتحويل إلى قيمة منطقيّة (Boolean value). انظر المقارنات للاستزادة.

العمليات المنطقيّة قابلة للتطبيق على جميع الكائنات كذلك، وتدعم اختبارات الصّحة (truth tests)، واختبارات الهويّة (identity tests)، وكذلك العوامل المنطقيّة (boolean operations):

operator.not_(obj)‎‎

operator.‎__not__‎(obj)‎‎

مُكافئة للتعبير ‎‎not obj (لاحظ أنّه لا وجود لتابعٍ خاصّ باسم ‎__not__‎()‎ لنُسخ الكائنات في بايثون؛ إذ أنّ المفسّر وحده يُعرّف هذه العمليّة. والنتيجة تتأثّر بالتابعين ‎__bool__‎()‎ و‎__len__‎()‎).

operator.truth(obj)‎‎

تُعيد القيمة True إن كان الكائن obj ذا قيمة صحيحة، وتُعيد القيمةَ False في غير ذلك من حالات.

هذه الدالة مُكافئة للدالة bool()‎.

operator.‎is_(a, b)‎‎‎

مُكافئة للتعبير ‎‎a is b‎ الذي يختبر هوية الكائن.

operator.‎is_not(a, b)‎‎‎

مُكافئة للتعبير ‎‎‎a is not b‎‎ الذي يختبر هوية الكائن.

العمليات الرياضيّة وعمليّات الأعداد الثنائية (bitwise operations) هي الأكثر عددًا:

operator.abs(obj)‎‎

operator.‎__abs__‎(obj)‎‎

تُعيد القيمة المطلقة (absolute value) للكائن ‎‎‎obj‎‎.

operator.and(a, b)‎‎‎

operator.‎__and__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a and b‎ .

operator.floordiv(a, b)‎‎‎

operator.‎__floordiv__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a // b.

operator.index(a)‎‎‎

operator.‎__index__‎(a)‎‎

تُعيد ‎‎a بعد تحويله إلى عدد صحيح، مُكافئة للاستدعاء a.‎__index__‎()‎‎.

operator.inv(obj)‎‎

operator.invert(obj)‎‎

operator.‎__inv__‎(obj)‎‎

operator.‎__invert__‎(obj)‎‎

تُعيد قيمة البت المعكوسة (bitwise inverse) للعدد ‎‎‎obj‎‎. وهي مكافئة للتعبير ‎‎‎‎~obj‎‎‎.

operator.lshift(a, b)‎‎‎

operator.‎__lshift__‎(a, b)‎‎

تُعيد العدد ‎‎a مُزاحًا إلى اليسار بالعدد ‎‎b.

operator.mod(a, b)‎‎‎

operator.‎__mod__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a % b.

operator.mul(a, b)‎‎‎

operator.‎__mul__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a * b للعددين ‎‎a و‎‎b.

operator.matmul(a, b)‎‎‎

operator.‎__matmul__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a @ b.

operator.neg(obj)‎‎

operator.‎__neg__‎(obj)‎‎

مُكافئة للتعبير ‎-‎obj‎.

operator.or_(a, b)‎‎‎

operator.‎__or__‎(a, b)‎‎

مُكافئة للتعبير ‎‎a or b.

operator.pos(obj)‎‎

operator.‎__pos__‎(obj)‎‎

مُكافئة للتعبير ‎‎+‎‎obj‎‎.

operator.pow(a, b)‎‎‎

operator.‎__pow__‎(a, b)‎‎

مُكافئة للتعبير ‎a ‎**‎ b‎ للعددين ‎‎a و‎‎b.

operator.rshift(a, b)‎‎‎

operator.‎__rshift__‎(a, b)‎‎

تُعيد العدد ‎‎a مُزاحًا إلى اليمين بالعدد ‎‎b.

operator.sub(a, b)‎‎‎

operator.‎__sub__‎(a, b)‎‎

مُكافئة للتعبير ‎a - b‎.

operator.truediv(a, b)‎‎‎

operator.‎__truediv__‎(a, b)‎‎

مُكافئة للتعبير ‎a / b‎ في الحالة التي يُساوي فيها ‎2/3‎ العدد ‎.66‎ عوضًا عن 0‎ وهذه القسمة معروفة أيضًا بالقسمة الحقيقيّة (true division).

operator.xor(a, b)‎‎‎

operator.‎__xor__‎(a, b)‎‎

تقوم بعمليّة أو المُقتصرة (exclusive or) لكل من ‎‎a و‎‎b.

العمليات التي تعمل مع التسلسلات (sequences) تشمل ما يلي، وبعضها يعمل مع كائنات الاقتران (mappings) كذلك:

operator.concat(a, b)‎‎‎

operator.‎__concat__‎(a, b)‎‎

مُكافئة للتعبير ‎a + b‎ لكل من التسلسلين ‎‎a و‎‎b.

operator.contains(a, b)‎‎‎

operator.‎__contains__‎(a, b)‎‎

مُكافئة للتعبير ‎‎b in a‎‎. لاحظ أن المعاملان معكوسان.

operator.countOf(a, b)‎‎‎

تُعيد عدد مرات وجود الكائن b في التسلسل a.

operator.delitem(a, b)‎‎‎

operator.‎__delitem__‎(a, b)‎‎

تحذف قيمة a في نقطة الفهرس b.

operator.getitem(a, b)‎‎‎

operator.‎__getitem__‎(a, b)‎‎

تُعيد قيمة a في نقطة الفهرس b.

operator.indexOf(a, b)‎‎‎

تُعيد نقطة فهرس أول وجود للكائن b في التسلسل a.

operator.setitem(‎a, b, c‎)‎‎‎

operator.‎__setitem__‎(‎a, b, c‎)‎‎

ضبط القيمة c لقيمة a في نقطة الفهرس b.

operator.length_hint(‎obj‎,‎ ‎default=0‎)‎‎‎

تُعيد طولًا تقريبيًّا للكائن obj. تُحاول في البداية إعادة الطول الفعليّ، فإن لم ينجح ذلك، فإنّ الدالة تُعيد قيمة تقريبيّة باستعمال ‎object.‎__length_hint__‎()‎، أو تُعيد القيمة الافتراضيّة الممرّرة للمُعامل default.

تُعرّف الوحدة operator أدوات مُساعدة للبحث عن الخاصيّات والعناصر كذلك. يُمكن استعمال هذه الدوال كمُعاملات للدوال map()‎، وsorted()‎، و‎itertools.groupby()‎ أو أي دالة أخرى تستقبل دالة كمعامل، وذلك لاستخراج قيم حقول معينة بسرعة.

operator.attrgetter(attr)‎‎

operator.attrgetter(*attrs)‎‎

تُعيد كائنًا قابلًا للاستدعاء للحصول على قيمة الخاصيّة attr من المُعامل الممرر للكائن القابل للاستدعاء. إن مُرّرت أكثر من خاصيّة واحدة للدالة، فسيُعاد صفّ من الخاصيّات. يُمكن لأسماء الخاصيّات أن تحتوي على النقاط كذلك. على سبيل المثال:

  • بعد التعيين ‎f‎ ‎=‎ ‎attrgetter‎('‎name‎'‎)‎‎، سيُعيد الاستدعاء ‎f(b)‎ الخاصيّة ‎b.name‎.
  • بعد التعيين ‎f‎ ‎=‎ ‎attrgetter‎(‎'name',‎ 'date'‎‎‎)‎‎‎، سيُعيد الاستدعاء ‎f(b)‎ الصفّ ‎‎(b.name‎,‎ ‎b.date)‎‎.
  • بعد التعيين ‎‎f = attrgetter‎('name.first', ‎'name.last')‎‎‎‎، سيُعيد الاستدعاء ‎f(b)‎ الصفّ ‎‎‎(b.name.first,‎ ‎b.name.last)‎‎‎.

والدالة مُكافئةً لما يلي:

def attrgetter(*items):
    if any(not isinstance(item, str) for item in items):
        raise TypeError('attribute name must be a string')
    if len(items) == 1:
        attr = items[0]
        def g(obj):
            return resolve_attr(obj, attr)
    else:
        def g(obj):
            return tuple(resolve_attr(obj, attr) for attr in items)
    return g

def resolve_attr(obj, attr):
    for name in attr.split("."):
        obj = getattr(obj, name)
    return obj

operator.itemgetter(item)‎‎

operator.itemgetter(*items)‎‎

تُعيد كائنًا قابلًا للاستدعاء يحصل على قيمة العنصر item من المُعامل الممرر باستعمال تابعه ‎__‎getitem‎__‎()‎. إن مُرّر أكثر من عنصر واحد للدالة، فسيُعاد صفّ من القيم. على سبيل المثال:

  • بعد التعيين ‎f‎ ‎=‎ ‎attrgetter‎('‎name‎'‎)‎‎، سيُعيد الاستدعاء ‎f(r)‎ القيمة ‎r[2]‎‎.
  • بعد التعيين ‎g = itemgetter(2, 5, 3)‎، سيُعيد الاستدعاء ‎g(r)‎ الصف ‎(r[2], r[5], r[3])‎‎.

والدالة مُكافئةً لما يلي:

def itemgetter(*items):
    if len(items) == 1:
        item = items[0]
        def g(obj):
            return obj[item]
    else:
        def g(obj):
            return tuple(obj[item] for item in items)
    return g

يُمكن للعناصر أن تكون من أي نوع يقبله التابع ‎__‎getitem‎__‎()‎ الخاص بالمعامل. القواميس تقبل أي قيمة قابلة للتجزئة (hashable value). والقوائم، والصفوف، والسلاسل النصية تقبل فهرسًا (index) أو تشريحًا (slice):

>>> itemgetter(1)('ABCDEFG')
'B'
>>> itemgetter(1,3,5)('ABCDEFG')
('B', 'D', 'F')
>>> itemgetter(slice(2,None))('ABCDEFG')
'CDEFG'

مثال على استعمال الدالة مع قاموس:

>>> soldier = dict(rank='captain', name='dotterbart')
>>> itemgetter('rank')(soldier)
'captain'

مثال على استعمال الدالة للحصول على حقول محدّدة من سجل صفوف:

>>> inventory = [('apple', 3), ('banana', 2), ('pear', 5), ('orange', 1)]
>>> getcount = itemgetter(1)
>>> list(map(getcount, inventory))
[3, 2, 5, 1]
>>> sorted(inventory, key=getcount)
[('orange', 1), ('banana', 2), ('apple', 3), ('pear', 5)]

operator.‎methodcaller‎(name‎[,‎ ‎args...‎]‎)‎

تعيد كائنًا قابلا للاستدعاء يستدعي التابع name الخاص بالمعامل الممرر. إن مُررت معاملات أخرى للدالة، فستُمرّر كمعاملات إلى التابع، مثلًا:

  • بعد التعيين ‎‎f = methodcaller('name')‎‎‎، سيُعيد الاستدعاءُ f(b)‎ استدعاءَ التابع ‎b.name()‎‎‎.
  • بعد التعيين ‎‎‎f = methodcaller(‎'‎name', ‎'foo', ‎bar=1)‎‎‎‎، سيُعيد الاستدعاءُ f(b)‎ استدعاءَ التابع ‎b.name('foo', bar=1)‎.
def methodcaller(name, *args, **kwargs):
    def caller(obj):
        return getattr(obj, name)(*args, **kwargs)
    return caller

ربط العوامل بالدوال

الجدول التالي يعرض علاقة العمليات برموز العوامل في بنية بايثون العامّة والدوال في الوحدة operator:

العملية البنية الدالة
الإضافة ‎‎a + b‎‎ ‎add(a, b)‎‎
التوحيد (Concatenation) ‎‎‎seq1 + seq2‎‎‎ ‎‎concat(seq1, seq2)‎‎‎
اختبار الاحتواء obj in seq‎‎‎ ‎contains(seq, obj)‎‎‎‎
القسمة ‎a / b‎‎‎‎ ‎truediv(a, b)‎
القسمة ‎‎a // b‎‎‎‎‎ ‎‎floordiv(a, b)‎
"و" على مستوى البت (Bitwise And) ‎‎a & b‎‎‎‎‎ ‎‎‎and_(a, b)‎
"أو" المُقتصرة على مستوى البت (Bitwise Exclusive Or) ‎‎a ^ b‎‎‎‎‎ ‎‎‎xor(a, b)‎
العكس على مستوى البت (Bitwise Inversion) ‎~ a‎‎‎‎‎‎ ‎invert(a)‎‎
"أو" على مستوى البت (Bitwise Or) b‎‎‎‎‎‎ ‎‎‎‎or_‎(a, b)‎
رفع القوة الجبرية (Exponentiation) ‎‎‎a ** b‎‎‎‎‎‎ ‎‎‎‎‎pow‎(a, b)‎
التحقق من الهوية ‎‎‎‎a is b‎‎‎‎‎‎‎ ‎‎‎‎‎‎is_‎(a, b)‎
التحقق من الهوية ‎‎‎‎a is not b ‎‎‎‎‎‎‎is_not(a, b)‎‎
التعيين فهرسيا ‎obj[k] = v‎ ‎‎‎‎‎‎‎‎setitem(obj, k, v)‎
الحذف فهرسيا ‎del ‎obj‎[k]‎‎ ‎delitem(obj, k)‎‎
الفهرسة ‎obj[k]‎ ‎‎getitem‎(obj, k)‎‎‎
الإزاحة إلى اليسار ‎‎a ‎<<‎ b‎‎ ‎lshift(a, b)‎
المقياس (Modulo) ‎‎a ‎%‎ b‎‎ ‎mod(a, b)‎
الضرب ‎‎a ‎* b‎‎ ‎mul(a, b)‎
ضرب المصفوفات (Matrix Multiplication) ‎‎a @ b‎‎ ‎matmul(a, b)‎
النقض الحسابي ‎- a‎‎‎ ‎‎neg(a)‎‎
النقض المنطقي ‎‎not a‎‎‎‎ ‎‎‎not_(a)‎‎‎
الإيجاب ‎‎‎+ a‎‎‎‎‎ ‎pos(a)‎
الإزاحة لليمين ‎a >> b‎‎‎‎‎‎ ‎rshift(a, b)‎
تعيين الشرائح (Slice Assignment) ‎‎seq[i:j]‎ ‎=‎ ‎values‎‎‎‎‎‎‎ ‎setitem‎(seq, ‎slice(i, j)‎, ‎values‎)‎‎
حذف الشرائح ‎del‎ ‎seq[i:j]‎‎‎‎‎‎‎‎ ‎‎delitem‎(‎seq, ‎slice‎(i, j)‎)‎‎
التشريح (Slicing) ‎seq[i:j]‎‎‎‎‎‎‎‎‎ ‎getitem‎(‎seq, slice‎(i, j)‎)‎‎
تنسيق السلاسل النصيّة ‎s ‎%‎ obj‎‎‎‎‎‎‎‎‎‎ ‎‎mod(s, obj)‎‎‎
اختبار الصحة ‎obj truth(obj)‎‎‎
الترتيب ‎‎a ‎<‎ b‎ ‎lt(a, b)‎
الترتيب ‎a ‎<=‎ b‎‎ ‎le(a, b)‎‎
المساواة ‎‎a == b‎‎‎ ‎eq(a, b)‎‎‎
الاختلاف ‎a != b‎‎‎‎ ‎‎ne(a, b)‎
الترتيب ‎‎a ‎‎>=‎‎ b‎ ‎ge(a, b)‎
الترتيب ‎a ‎‎>‎‎ b‎‎ ‎gt(a, b)‎‎

عوامل في الموقع (Inplace Operators)

تملك العديد من العمليات نُسخةً تُستعمل في الموقع، وتُوفّر الدوال التالية طريقة بدائيّة لإجراء هذه العمليات التي يُمكن القيام بها في بايثون عبر البنية العامة الخاصة باللغة؛ على سبيل المثال، الجملة ‎‎‎x += y‎‎ مكافئة للجملة ‎‎‎‎x = operator.iadd(x, y)‎. ويُمكن كذلك القول بأنّ الجملة ‎z = ‎operator.iadd(x, y)‎ مكافئة للجملة المركبة ‎z = x; z += y‎‎.

لاحظ في المثالين أعلاه أنّه عند استدعاء تابعِ "في الموقع"، فإن الحساب والتعيين يحدثان على خطوتين مختلفتين. الدوال أسفله تقوم بالخطوة الأولى فقط، أي استدعاء تابعِ "في الموقع". والخطوة الثانية التي هي التعيين لا تحدث.

في حالة الكائنات غير القابلة للتغيير (immutable)، كالسلاسل النصية، والأعداد، والصفوف، تُحسَبُ القيمة المُحدَّثَة، لكنها لا تُعيَّن إلى المُتغير المُدخل:

>>> a = 'hello'
>>> iadd(a, ' world')
'hello world'
>>> a
'hello'

في حالة الكائنات القابلة للتغيير (mutable)، كالقوائم والقواميس فسيقوم التابع بإجراء التحديث، لذا فلا حاجة للتعيين بعد ذلك:

>>> s = ['h', 'e', 'l', 'l', 'o']
>>> iadd(s, [' ', 'w', 'o', 'r', 'l', 'd'])
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
>>> s
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']

operator.iadd(a, b)‎‎‎

operator.‎__iadd__‎(a, b)‎‎

الجملة ‎a = ‎iadd(a, b)‎ مكافئة للجملة ‎a ‎+=‎ b‎.

operator.iand(a, b)‎‎‎

operator.‎__iand__‎(a, b)‎‎

الجملة ‎a = ‎iand(a, b)‎ مكافئة للجملة ‎a &=‎ b‎.

operator.iconcat(a, b)‎‎‎

operator.‎__iconcat__‎(a, b)‎‎

الجملة ‎a = ‎iconcat(a, b)‎‎ مكافئة للجملة ‎a +=‎ b‎ لكل من التسلسلين ‎‎a و‎‎b.

operator.ifloordiv(a, b)‎‎‎

operator.‎__ifloordiv__‎(a, b)‎‎

الجملة ‎a = ‎ifloordiv(a, b)‎‎ مكافئة للجملة ‎a //=‎ b‎.

operator.ilshift(a, b)‎‎‎

operator.‎__ilshift__‎(a, b)‎‎

الجملة ‎a = ‎ilshift(a, b)‎‎ مكافئة للجملة ‎a ‎<<=‎‎ b‎.

operator.imod(a, b)‎‎‎

operator.‎__imod__‎(a, b)‎‎

الجملة ‎a = ‎imod(a, b)‎‎ مكافئة للجملة ‎a ‎‎%=‎‎‎ b‎.

operator.imul(a, b)‎‎‎

operator.‎__imul__‎(a, b)‎‎

الجملة ‎a = ‎imul(a, b)‎‎ مكافئة للجملة ‎a ‎‎*=‎‎‎ b‎.

operator.imatmul(a, b)‎‎‎

operator.‎__imatmul__‎(a, b)‎‎

الجملة ‎a = ‎imatmul(a, b)‎‎ مكافئة للجملة ‎a ‎‎@=‎‎‎ b‎.

operator.ior(a, b)‎‎‎

operator.‎__ior__‎(a, b)‎‎

الجملة ‎a = ‎ior(a, b)‎‎ مكافئة للجملة ‎a ‎‎|=‎‎‎ b‎.

operator.ipow(a, b)‎‎‎

operator.‎__ipow__‎(a, b)‎‎

الجملة ‎a = ‎ipow(a, b)‎‎ مكافئة للجملة ‎a ‎‎**=‎‎‎ b‎.

operator.irshift(a, b)‎‎‎

operator.‎__irshift__‎(a, b)‎‎

الجملة ‎a = ‎irshift(a, b)‎‎ مكافئة للجملة ‎a ‎‎>>=‎‎‎ b‎.

operator.isub(a, b)‎‎‎

operator.‎__isub__‎(a, b)‎‎

الجملة ‎a = ‎isub(a, b)‎‎ مكافئة للجملة ‎a -=‎‎‎ b‎.

operator.itruediv(a, b)‎‎‎

operator.‎__itruediv__‎(a, b)‎‎

الجملة ‎a = ‎itruediv(a, b)‎‎ مكافئة للجملة ‎a /=‎‎‎ b‎.

operator.ixor(a, b)‎‎‎

operator.‎__ixor__‎(a, b)‎‎

الجملة ‎a = ‎ixor(a, b)‎‎ مكافئة للجملة ‎a ^=‎‎‎ b‎.

مصادر