operator --- عملگرهای استاندارد به‌عنوان توابع

کد منبع: Lib/operator.py


ماژول operator مجموعه‌ای از توابع کارآمد متناظر با عملگرهای ذاتی پایتون را اکسپورت می‌کند. برای مثال، operator.add(x, y) معادل عبارت x+y است. نام‌های بسیاری از توابع، همان نام‌هایی هستند که برای متدهای ویژه استفاده می‌شوند، بدون دو زیرخط. برای سازگاری با نسخه‌های قدیمی، بسیاری از این توابع گونه‌ای با حفظ دو زیرخط دارند. گونه‌های بدون دو زیرخط برای وضوح بیشتر ترجیح داده می‌شوند.

این توابع به دسته‌هایی تقسیم می‌شوند که مقایسه‌ی شیء‌ها، عملیات منطقی، عملیات ریاضی و عملیات دنباله را انجام می‌دهند.

توابع مقایسه‌ی اشیاء برای همه‌ی اشیاء مفید هستند و نام خود را از عملگرهای مقایسه‌ی غنی‌ای که پشتیبانی می‌کنند، گرفته‌اند:

operator.lt(a, b)
operator.le(a, b)
operator.eq(a, b)
operator.ne(a, b)
operator.ge(a, b)
operator.gt(a, b)
operator.__lt__(a, b)
operator.__le__(a, b)
operator.__eq__(a, b)
operator.__ne__(a, b)
operator.__ge__(a, b)
operator.__gt__(a, b)

«مقایسه‌های غنی» بین a و b را انجام می‌دهد. به‌طور مشخص، lt(a, b) معادل a < b است، le(a, b) معادل a <= b است، eq(a, b) معادل a == b است، ne(a, b) معادل a != b است، gt(a, b) معادل a > b است و ge(a, b) معادل a >= b است. توجه داشته باشید که این توابع می‌توانند هر مقداری را برگردانند، که ممکن است بتوان آن را به‌عنوان یک مقدار بولی تفسیر کرد یا نه. برای اطلاعات بیشتر درباره‌ی مقایسه‌های غنی، مقایسه‌ها را ببینید.

عملیات منطقی نیز به‌طور کلی برای همه اشیاء قابل اعمال هستند و از آزمون‌های درستی، آزمون‌های هویت و عملیات بولی پشتیبانی می‌کنند:

operator.not_(obj)
operator.__not__(obj)

نتیجه‌ی not obj را برمی‌گرداند. (توجه داشته باشید که هیچ متد __not__() برای نمونه‌های شیء وجود ندارد؛ تنها هسته‌ی مفسر این عملیات را تعریف می‌کند. نتیجه تحت تأثیر متدهای __bool__() و __len__() است.)

operator.truth(obj)

اگر obj درست باشد، True را برمی‌گرداند و در غیر این صورت False را. این معادل استفاده از سازنده‌ی bool است.

operator.is_(a, b)

a is b را برمی‌گرداند. هویت شیء را می‌آزماید.

operator.is_not(a, b)

a is not b را برمی‌گرداند. هویت شیء را آزمایش می‌کند.

operator.is_none(a)

a is None را برمی‌گرداند. هویت شیء را می‌آزماید.

اضافه شده در نسخه‌ی 3.14.

operator.is_not_none(a)

a is not None را برمی‌گرداند. هویت شیء را آزمایش می‌کند.

اضافه شده در نسخه‌ی 3.14.

عملیات ریاضی و بیتی بیشترین تعداد را دارند:

operator.abs(obj)
operator.__abs__(obj)

مقدار مطلق obj را برمی‌گرداند.

operator.add(a, b)
operator.__add__(a, b)

a + b را برای a و b عددی برمی‌گرداند.

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

a & b را برمی‌گرداند.

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

a // b را برمی‌گرداند.

operator.index(a)
operator.__index__(a)

a را به‌صورت عدد صحیح برمی‌گرداند. معادل a.__index__() است.

تغییر یافته در نسخه‌ی 3.10: نتیجه همیشه از نوع دقیق int است. پیش از این، نتیجه می‌توانست نمونه‌ای از یک زیرکلاس از int باشد.

operator.inv(obj)
operator.invert(obj)
operator.__inv__(obj)
operator.__invert__(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 را برمی‌گرداند.

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

a @ b را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.5.

operator.neg(obj)
operator.__neg__(obj)

obj را منفی‌شده برمی‌گرداند (-obj).

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

a | b را برمی‌گرداند.

operator.pos(obj)
operator.__pos__(obj)

+obj را برمی‌گرداند.

operator.pow(a, b)
operator.__pow__(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. این به‌عنوان تقسیم «واقعی» نیز شناخته می‌شود.

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

a ^ b را برمی‌گرداند.

عملیاتی که با دنباله‌ها کار می‌کنند (برخی از آن‌ها با نگاشت‌ها نیز کار می‌کنند) عبارتند از:

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)

مقدار a را در اندیس b به c تنظیم کنید.

operator.length_hint(obj, default=0)

طول تخمینی شیء obj را برمی‌گرداند. ابتدا تلاش می‌کند طول واقعی آن را برگرداند، سپس تخمینی را با استفاده از object.__length_hint__() برمی‌گرداند، و در نهایت مقدار پیش‌فرض را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.4.

عملیات زیر با فراخوانی‌پذیرها کار می‌کند:

operator.call(obj, /, *args, **kwargs)
operator.__call__(obj, /, *args, **kwargs)

obj(*args, **kwargs) را برمی‌گرداند.

اضافه شده در نسخه‌ی 3.11.

ماژول 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 = itemgetter(2)، فراخوانی 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 را می‌پذیرند. فهرست‌ها، تاپل‌ها و رشته‌ها یک اندیس یا یک اسلایس را می‌پذیرند:

>>> 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'

نمونه‌ای از استفاده از itemgetter() برای بازیابی فیلدهای مشخص از یک رکورد تاپلی:

>>> 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, **kwargs)

یک شیء فراخوانی‌پذیر برمی‌گرداند که متد 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)

الحاق

seq1 + seq2

concat(seq1, seq2)

آزمون عضویت

obj in seq

contains(seq, obj)

تقسیم

a / b

truediv(a, b)

تقسیم

a // b

floordiv(a, b)

و بیت‌به‌بیت، یا اشتراک

a & b

and_(a, b)

یا انحصاری بیت‌به‌بیت، یا تفاوت متقارن

a ^ b

xor(a, b)

وارونگی بیتی، یا مکمل

~ a

invert(a)

یای بیتی، یا اجتماع

a | b

or_(a, b)

توان‌رسانی

a ** b

pow(a, b)

هویت

a is b

is_(a, b)

هویت

a is not b

is_not(a, b)

هویت

a is None

is_none(a)

هویت

a is not None

is_not_none(a)

انتساب اندیسی

obj[k] = v

setitem(obj, k, v)

حذف با اندیس

del obj[k]

delitem(obj, k)

اندیس‌گذاری

obj[k]

getitem(obj, k)

شیفت چپ

a << b

lshift(a, b)

باقی‌مانده

a % b

mod(a, b)

ضرب

a * b

mul(a, b)

ضرب ماتریس‌ها

a @ b

matmul(a, b)

منفی‌سازی (حسابی)

- a

neg(a)

نفی (منطقی)

not a

not_(a)

مثبت

+ a

pos(a)

شیفت به راست

a >> b

rshift(a, b)

انتساب اسلایس

seq[i:j] = values

setitem(seq, slice(i, j), values)

حذف اسلایس

del seq[i:j]

delitem(seq, slice(i, j))

اسلایس‌کردن

seq[i:j]

getitem(seq, slice(i, j))

قالب‌بندی رشته

s % obj

mod(s, obj)

تفریق

a - b

sub(a, b)

آزمون درستی

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)

عملگرهای درجا

بسیاری از عملیات‌ها یک نسخه‌ی «درجا» (in-place) دارند. در زیر توابعی فهرست شده‌اند که نسبت به سینتکس معمول، دسترسی اولیه‌تری به عملگرهای درجا فراهم می‌کنند؛ برای مثال، دستور x += y معادل x = operator.iadd(x, y) است. راه دیگر بیان این موضوع این است که z = operator.iadd(x, y) معادل دستور ترکیبی z = x; z += y است.

در این مثال‌ها، توجه داشته باشید که هنگامی که یک متد درجا (in-place) فراخوانی می‌شود، محاسبه و انتساب در دو مرحله‌ی جداگانه انجام می‌شوند. توابع درجا، که در زیر فهرست شده‌اند، تنها مرحله‌ی اول، یعنی فراخوانی متد درجا، را انجام می‌دهند. مرحله‌ی دوم، یعنی انتساب، انجام نمی‌شود.

برای اهداف تغییرناپذیر مانند رشته‌ها، اعداد و تاپل‌ها، مقدار به‌روزشده محاسبه می‌شود، اما به متغیر ورودی انتساب داده نمی‌شود:

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

برای هدف‌های تغییرپذیر مانند فهرست‌ها و دیکشنری‌ها، متد درجا به‌روزرسانی را انجام می‌دهد، بنابراین دیگر نیازی به انتساب بعدی نیست:

>>> 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 است.

اضافه شده در نسخه‌ی 3.5.

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 است.