• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1"""
2Operator Interface
3
4This module exports a set of functions corresponding to the intrinsic
5operators of Python.  For example, operator.add(x, y) is equivalent
6to the expression x+y.  The function names are those used for special
7methods; variants without leading and trailing '__' are also provided
8for convenience.
9
10This is the pure Python implementation of the module.
11"""
12
13__all__ = ['abs', 'add', 'and_', 'attrgetter', 'concat', 'contains', 'countOf',
14           'delitem', 'eq', 'floordiv', 'ge', 'getitem', 'gt', 'iadd', 'iand',
15           'iconcat', 'ifloordiv', 'ilshift', 'imatmul', 'imod', 'imul',
16           'index', 'indexOf', 'inv', 'invert', 'ior', 'ipow', 'irshift',
17           'is_', 'is_not', 'isub', 'itemgetter', 'itruediv', 'ixor', 'le',
18           'length_hint', 'lshift', 'lt', 'matmul', 'methodcaller', 'mod',
19           'mul', 'ne', 'neg', 'not_', 'or_', 'pos', 'pow', 'rshift',
20           'setitem', 'sub', 'truediv', 'truth', 'xor']
21
22from builtins import abs as _abs
23
24
25# Comparison Operations *******************************************************#
26
27def lt(a, b):
28    "Same as a < b."
29    return a < b
30
31def le(a, b):
32    "Same as a <= b."
33    return a <= b
34
35def eq(a, b):
36    "Same as a == b."
37    return a == b
38
39def ne(a, b):
40    "Same as a != b."
41    return a != b
42
43def ge(a, b):
44    "Same as a >= b."
45    return a >= b
46
47def gt(a, b):
48    "Same as a > b."
49    return a > b
50
51# Logical Operations **********************************************************#
52
53def not_(a):
54    "Same as not a."
55    return not a
56
57def truth(a):
58    "Return True if a is true, False otherwise."
59    return True if a else False
60
61def is_(a, b):
62    "Same as a is b."
63    return a is b
64
65def is_not(a, b):
66    "Same as a is not b."
67    return a is not b
68
69# Mathematical/Bitwise Operations *********************************************#
70
71def abs(a):
72    "Same as abs(a)."
73    return _abs(a)
74
75def add(a, b):
76    "Same as a + b."
77    return a + b
78
79def and_(a, b):
80    "Same as a & b."
81    return a & b
82
83def floordiv(a, b):
84    "Same as a // b."
85    return a // b
86
87def index(a):
88    "Same as a.__index__()."
89    return a.__index__()
90
91def inv(a):
92    "Same as ~a."
93    return ~a
94invert = inv
95
96def lshift(a, b):
97    "Same as a << b."
98    return a << b
99
100def mod(a, b):
101    "Same as a % b."
102    return a % b
103
104def mul(a, b):
105    "Same as a * b."
106    return a * b
107
108def matmul(a, b):
109    "Same as a @ b."
110    return a @ b
111
112def neg(a):
113    "Same as -a."
114    return -a
115
116def or_(a, b):
117    "Same as a | b."
118    return a | b
119
120def pos(a):
121    "Same as +a."
122    return +a
123
124def pow(a, b):
125    "Same as a ** b."
126    return a ** b
127
128def rshift(a, b):
129    "Same as a >> b."
130    return a >> b
131
132def sub(a, b):
133    "Same as a - b."
134    return a - b
135
136def truediv(a, b):
137    "Same as a / b."
138    return a / b
139
140def xor(a, b):
141    "Same as a ^ b."
142    return a ^ b
143
144# Sequence Operations *********************************************************#
145
146def concat(a, b):
147    "Same as a + b, for a and b sequences."
148    if not hasattr(a, '__getitem__'):
149        msg = "'%s' object can't be concatenated" % type(a).__name__
150        raise TypeError(msg)
151    return a + b
152
153def contains(a, b):
154    "Same as b in a (note reversed operands)."
155    return b in a
156
157def countOf(a, b):
158    "Return the number of times b occurs in a."
159    count = 0
160    for i in a:
161        if i == b:
162            count += 1
163    return count
164
165def delitem(a, b):
166    "Same as del a[b]."
167    del a[b]
168
169def getitem(a, b):
170    "Same as a[b]."
171    return a[b]
172
173def indexOf(a, b):
174    "Return the first index of b in a."
175    for i, j in enumerate(a):
176        if j == b:
177            return i
178    else:
179        raise ValueError('sequence.index(x): x not in sequence')
180
181def setitem(a, b, c):
182    "Same as a[b] = c."
183    a[b] = c
184
185def length_hint(obj, default=0):
186    """
187    Return an estimate of the number of items in obj.
188    This is useful for presizing containers when building from an iterable.
189
190    If the object supports len(), the result will be exact. Otherwise, it may
191    over- or under-estimate by an arbitrary amount. The result will be an
192    integer >= 0.
193    """
194    if not isinstance(default, int):
195        msg = ("'%s' object cannot be interpreted as an integer" %
196               type(default).__name__)
197        raise TypeError(msg)
198
199    try:
200        return len(obj)
201    except TypeError:
202        pass
203
204    try:
205        hint = type(obj).__length_hint__
206    except AttributeError:
207        return default
208
209    try:
210        val = hint(obj)
211    except TypeError:
212        return default
213    if val is NotImplemented:
214        return default
215    if not isinstance(val, int):
216        msg = ('__length_hint__ must be integer, not %s' %
217               type(val).__name__)
218        raise TypeError(msg)
219    if val < 0:
220        msg = '__length_hint__() should return >= 0'
221        raise ValueError(msg)
222    return val
223
224# Generalized Lookup Objects **************************************************#
225
226class attrgetter:
227    """
228    Return a callable object that fetches the given attribute(s) from its operand.
229    After f = attrgetter('name'), the call f(r) returns r.name.
230    After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).
231    After h = attrgetter('name.first', 'name.last'), the call h(r) returns
232    (r.name.first, r.name.last).
233    """
234    __slots__ = ('_attrs', '_call')
235
236    def __init__(self, attr, *attrs):
237        if not attrs:
238            if not isinstance(attr, str):
239                raise TypeError('attribute name must be a string')
240            self._attrs = (attr,)
241            names = attr.split('.')
242            def func(obj):
243                for name in names:
244                    obj = getattr(obj, name)
245                return obj
246            self._call = func
247        else:
248            self._attrs = (attr,) + attrs
249            getters = tuple(map(attrgetter, self._attrs))
250            def func(obj):
251                return tuple(getter(obj) for getter in getters)
252            self._call = func
253
254    def __call__(self, obj):
255        return self._call(obj)
256
257    def __repr__(self):
258        return '%s.%s(%s)' % (self.__class__.__module__,
259                              self.__class__.__qualname__,
260                              ', '.join(map(repr, self._attrs)))
261
262    def __reduce__(self):
263        return self.__class__, self._attrs
264
265class itemgetter:
266    """
267    Return a callable object that fetches the given item(s) from its operand.
268    After f = itemgetter(2), the call f(r) returns r[2].
269    After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])
270    """
271    __slots__ = ('_items', '_call')
272
273    def __init__(self, item, *items):
274        if not items:
275            self._items = (item,)
276            def func(obj):
277                return obj[item]
278            self._call = func
279        else:
280            self._items = items = (item,) + items
281            def func(obj):
282                return tuple(obj[i] for i in items)
283            self._call = func
284
285    def __call__(self, obj):
286        return self._call(obj)
287
288    def __repr__(self):
289        return '%s.%s(%s)' % (self.__class__.__module__,
290                              self.__class__.__name__,
291                              ', '.join(map(repr, self._items)))
292
293    def __reduce__(self):
294        return self.__class__, self._items
295
296class methodcaller:
297    """
298    Return a callable object that calls the given method on its operand.
299    After f = methodcaller('name'), the call f(r) returns r.name().
300    After g = methodcaller('name', 'date', foo=1), the call g(r) returns
301    r.name('date', foo=1).
302    """
303    __slots__ = ('_name', '_args', '_kwargs')
304
305    def __init__(*args, **kwargs):
306        if len(args) < 2:
307            msg = "methodcaller needs at least one argument, the method name"
308            raise TypeError(msg)
309        self = args[0]
310        self._name = args[1]
311        if not isinstance(self._name, str):
312            raise TypeError('method name must be a string')
313        self._args = args[2:]
314        self._kwargs = kwargs
315
316    def __call__(self, obj):
317        return getattr(obj, self._name)(*self._args, **self._kwargs)
318
319    def __repr__(self):
320        args = [repr(self._name)]
321        args.extend(map(repr, self._args))
322        args.extend('%s=%r' % (k, v) for k, v in self._kwargs.items())
323        return '%s.%s(%s)' % (self.__class__.__module__,
324                              self.__class__.__name__,
325                              ', '.join(args))
326
327    def __reduce__(self):
328        if not self._kwargs:
329            return self.__class__, (self._name,) + self._args
330        else:
331            from functools import partial
332            return partial(self.__class__, self._name, **self._kwargs), self._args
333
334
335# In-place Operations *********************************************************#
336
337def iadd(a, b):
338    "Same as a += b."
339    a += b
340    return a
341
342def iand(a, b):
343    "Same as a &= b."
344    a &= b
345    return a
346
347def iconcat(a, b):
348    "Same as a += b, for a and b sequences."
349    if not hasattr(a, '__getitem__'):
350        msg = "'%s' object can't be concatenated" % type(a).__name__
351        raise TypeError(msg)
352    a += b
353    return a
354
355def ifloordiv(a, b):
356    "Same as a //= b."
357    a //= b
358    return a
359
360def ilshift(a, b):
361    "Same as a <<= b."
362    a <<= b
363    return a
364
365def imod(a, b):
366    "Same as a %= b."
367    a %= b
368    return a
369
370def imul(a, b):
371    "Same as a *= b."
372    a *= b
373    return a
374
375def imatmul(a, b):
376    "Same as a @= b."
377    a @= b
378    return a
379
380def ior(a, b):
381    "Same as a |= b."
382    a |= b
383    return a
384
385def ipow(a, b):
386    "Same as a **= b."
387    a **=b
388    return a
389
390def irshift(a, b):
391    "Same as a >>= b."
392    a >>= b
393    return a
394
395def isub(a, b):
396    "Same as a -= b."
397    a -= b
398    return a
399
400def itruediv(a, b):
401    "Same as a /= b."
402    a /= b
403    return a
404
405def ixor(a, b):
406    "Same as a ^= b."
407    a ^= b
408    return a
409
410
411try:
412    from _operator import *
413except ImportError:
414    pass
415else:
416    from _operator import __doc__
417
418# All of these "__func__ = func" assignments have to happen after importing
419# from _operator to make sure they're set to the right function
420__lt__ = lt
421__le__ = le
422__eq__ = eq
423__ne__ = ne
424__ge__ = ge
425__gt__ = gt
426__not__ = not_
427__abs__ = abs
428__add__ = add
429__and__ = and_
430__floordiv__ = floordiv
431__index__ = index
432__inv__ = inv
433__invert__ = invert
434__lshift__ = lshift
435__mod__ = mod
436__mul__ = mul
437__matmul__ = matmul
438__neg__ = neg
439__or__ = or_
440__pos__ = pos
441__pow__ = pow
442__rshift__ = rshift
443__sub__ = sub
444__truediv__ = truediv
445__xor__ = xor
446__concat__ = concat
447__contains__ = contains
448__delitem__ = delitem
449__getitem__ = getitem
450__setitem__ = setitem
451__iadd__ = iadd
452__iand__ = iand
453__iconcat__ = iconcat
454__ifloordiv__ = ifloordiv
455__ilshift__ = ilshift
456__imod__ = imod
457__imul__ = imul
458__imatmul__ = imatmul
459__ior__ = ior
460__ipow__ = ipow
461__irshift__ = irshift
462__isub__ = isub
463__itruediv__ = itruediv
464__ixor__ = ixor
465