• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 """
2 Operator Interface
3 
4 This module exports a set of functions corresponding to the intrinsic
5 operators of Python.  For example, operator.add(x, y) is equivalent
6 to the expression x+y.  The function names are those used for special
7 methods; variants without leading and trailing '__' are also provided
8 for convenience.
9 
10 This 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 
22 from builtins import abs as _abs
23 
24 
25 # Comparison Operations *******************************************************#
26 
27 def lt(a, b):
28     "Same as a < b."
29     return a < b
30 
31 def le(a, b):
32     "Same as a <= b."
33     return a <= b
34 
35 def eq(a, b):
36     "Same as a == b."
37     return a == b
38 
39 def ne(a, b):
40     "Same as a != b."
41     return a != b
42 
43 def ge(a, b):
44     "Same as a >= b."
45     return a >= b
46 
47 def gt(a, b):
48     "Same as a > b."
49     return a > b
50 
51 # Logical Operations **********************************************************#
52 
53 def not_(a):
54     "Same as not a."
55     return not a
56 
57 def truth(a):
58     "Return True if a is true, False otherwise."
59     return True if a else False
60 
61 def is_(a, b):
62     "Same as a is b."
63     return a is b
64 
65 def is_not(a, b):
66     "Same as a is not b."
67     return a is not b
68 
69 # Mathematical/Bitwise Operations *********************************************#
70 
71 def abs(a):
72     "Same as abs(a)."
73     return _abs(a)
74 
75 def add(a, b):
76     "Same as a + b."
77     return a + b
78 
79 def and_(a, b):
80     "Same as a & b."
81     return a & b
82 
83 def floordiv(a, b):
84     "Same as a // b."
85     return a // b
86 
87 def index(a):
88     "Same as a.__index__()."
89     return a.__index__()
90 
91 def inv(a):
92     "Same as ~a."
93     return ~a
94 invert = inv
95 
96 def lshift(a, b):
97     "Same as a << b."
98     return a << b
99 
100 def mod(a, b):
101     "Same as a % b."
102     return a % b
103 
104 def mul(a, b):
105     "Same as a * b."
106     return a * b
107 
108 def matmul(a, b):
109     "Same as a @ b."
110     return a @ b
111 
112 def neg(a):
113     "Same as -a."
114     return -a
115 
116 def or_(a, b):
117     "Same as a | b."
118     return a | b
119 
120 def pos(a):
121     "Same as +a."
122     return +a
123 
124 def pow(a, b):
125     "Same as a ** b."
126     return a ** b
127 
128 def rshift(a, b):
129     "Same as a >> b."
130     return a >> b
131 
132 def sub(a, b):
133     "Same as a - b."
134     return a - b
135 
136 def truediv(a, b):
137     "Same as a / b."
138     return a / b
139 
140 def xor(a, b):
141     "Same as a ^ b."
142     return a ^ b
143 
144 # Sequence Operations *********************************************************#
145 
146 def 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 
153 def contains(a, b):
154     "Same as b in a (note reversed operands)."
155     return b in a
156 
157 def countOf(a, b):
158     "Return the number of items in a which are, or which equal, b."
159     count = 0
160     for i in a:
161         if i is b or i == b:
162             count += 1
163     return count
164 
165 def delitem(a, b):
166     "Same as del a[b]."
167     del a[b]
168 
169 def getitem(a, b):
170     "Same as a[b]."
171     return a[b]
172 
173 def indexOf(a, b):
174     "Return the first index of b in a."
175     for i, j in enumerate(a):
176         if j is b or j == b:
177             return i
178     else:
179         raise ValueError('sequence.index(x): x not in sequence')
180 
181 def setitem(a, b, c):
182     "Same as a[b] = c."
183     a[b] = c
184 
185 def 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 
226 class 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 
265 class 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 
296 class 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__(self, name, /, *args, **kwargs):
306         self._name = name
307         if not isinstance(self._name, str):
308             raise TypeError('method name must be a string')
309         self._args = args
310         self._kwargs = kwargs
311 
312     def __call__(self, obj):
313         return getattr(obj, self._name)(*self._args, **self._kwargs)
314 
315     def __repr__(self):
316         args = [repr(self._name)]
317         args.extend(map(repr, self._args))
318         args.extend('%s=%r' % (k, v) for k, v in self._kwargs.items())
319         return '%s.%s(%s)' % (self.__class__.__module__,
320                               self.__class__.__name__,
321                               ', '.join(args))
322 
323     def __reduce__(self):
324         if not self._kwargs:
325             return self.__class__, (self._name,) + self._args
326         else:
327             from functools import partial
328             return partial(self.__class__, self._name, **self._kwargs), self._args
329 
330 
331 # In-place Operations *********************************************************#
332 
333 def iadd(a, b):
334     "Same as a += b."
335     a += b
336     return a
337 
338 def iand(a, b):
339     "Same as a &= b."
340     a &= b
341     return a
342 
343 def iconcat(a, b):
344     "Same as a += b, for a and b sequences."
345     if not hasattr(a, '__getitem__'):
346         msg = "'%s' object can't be concatenated" % type(a).__name__
347         raise TypeError(msg)
348     a += b
349     return a
350 
351 def ifloordiv(a, b):
352     "Same as a //= b."
353     a //= b
354     return a
355 
356 def ilshift(a, b):
357     "Same as a <<= b."
358     a <<= b
359     return a
360 
361 def imod(a, b):
362     "Same as a %= b."
363     a %= b
364     return a
365 
366 def imul(a, b):
367     "Same as a *= b."
368     a *= b
369     return a
370 
371 def imatmul(a, b):
372     "Same as a @= b."
373     a @= b
374     return a
375 
376 def ior(a, b):
377     "Same as a |= b."
378     a |= b
379     return a
380 
381 def ipow(a, b):
382     "Same as a **= b."
383     a **=b
384     return a
385 
386 def irshift(a, b):
387     "Same as a >>= b."
388     a >>= b
389     return a
390 
391 def isub(a, b):
392     "Same as a -= b."
393     a -= b
394     return a
395 
396 def itruediv(a, b):
397     "Same as a /= b."
398     a /= b
399     return a
400 
401 def ixor(a, b):
402     "Same as a ^= b."
403     a ^= b
404     return a
405 
406 
407 try:
408     from _operator import *
409 except ImportError:
410     pass
411 else:
412     from _operator import __doc__
413 
414 # All of these "__func__ = func" assignments have to happen after importing
415 # from _operator to make sure they're set to the right function
416 __lt__ = lt
417 __le__ = le
418 __eq__ = eq
419 __ne__ = ne
420 __ge__ = ge
421 __gt__ = gt
422 __not__ = not_
423 __abs__ = abs
424 __add__ = add
425 __and__ = and_
426 __floordiv__ = floordiv
427 __index__ = index
428 __inv__ = inv
429 __invert__ = invert
430 __lshift__ = lshift
431 __mod__ = mod
432 __mul__ = mul
433 __matmul__ = matmul
434 __neg__ = neg
435 __or__ = or_
436 __pos__ = pos
437 __pow__ = pow
438 __rshift__ = rshift
439 __sub__ = sub
440 __truediv__ = truediv
441 __xor__ = xor
442 __concat__ = concat
443 __contains__ = contains
444 __delitem__ = delitem
445 __getitem__ = getitem
446 __setitem__ = setitem
447 __iadd__ = iadd
448 __iand__ = iand
449 __iconcat__ = iconcat
450 __ifloordiv__ = ifloordiv
451 __ilshift__ = ilshift
452 __imod__ = imod
453 __imul__ = imul
454 __imatmul__ = imatmul
455 __ior__ = ior
456 __ipow__ = ipow
457 __irshift__ = irshift
458 __isub__ = isub
459 __itruediv__ = itruediv
460 __ixor__ = ixor
461