blob: 0e2e53efc69a77dca0081ad67e2deb0accb9a288 [file] [log] [blame]
Antoine Pitroua85017f2013-04-20 19:21:44 +02001"""
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',
Tal Einat988df6a2015-06-07 19:21:01 +030015 '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',
Raymond Hettingera1fc9492015-11-02 00:39:56 -050020 'setitem', 'sub', 'truediv', 'truth', 'xor']
Antoine Pitroua85017f2013-04-20 19:21:44 +020021
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
Benjamin Petersond51374e2014-04-09 23:55:56 -0400108def matmul(a, b):
109 "Same as a @ b."
110 return a @ b
111
Antoine Pitroua85017f2013-04-20 19:21:44 +0200112def 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.
Ezio Melotti0fbdf262013-05-08 10:56:32 +0300229 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
Antoine Pitroua85017f2013-04-20 19:21:44 +0200232 (r.name.first, r.name.last).
233 """
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300234 __slots__ = ('_attrs', '_call')
235
Antoine Pitroua85017f2013-04-20 19:21:44 +0200236 def __init__(self, attr, *attrs):
237 if not attrs:
238 if not isinstance(attr, str):
239 raise TypeError('attribute name must be a string')
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300240 self._attrs = (attr,)
Antoine Pitroua85017f2013-04-20 19:21:44 +0200241 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:
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300248 self._attrs = (attr,) + attrs
249 getters = tuple(map(attrgetter, self._attrs))
Antoine Pitroua85017f2013-04-20 19:21:44 +0200250 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
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300257 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
Antoine Pitroua85017f2013-04-20 19:21:44 +0200265class itemgetter:
266 """
267 Return a callable object that fetches the given item(s) from its operand.
Ezio Melotti0fbdf262013-05-08 10:56:32 +0300268 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])
Antoine Pitroua85017f2013-04-20 19:21:44 +0200270 """
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300271 __slots__ = ('_items', '_call')
272
Antoine Pitroua85017f2013-04-20 19:21:44 +0200273 def __init__(self, item, *items):
274 if not items:
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300275 self._items = (item,)
Antoine Pitroua85017f2013-04-20 19:21:44 +0200276 def func(obj):
277 return obj[item]
278 self._call = func
279 else:
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300280 self._items = items = (item,) + items
Antoine Pitroua85017f2013-04-20 19:21:44 +0200281 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
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300288 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
Antoine Pitroua85017f2013-04-20 19:21:44 +0200296class 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 """
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300303 __slots__ = ('_name', '_args', '_kwargs')
Antoine Pitroua85017f2013-04-20 19:21:44 +0200304
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]
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300311 if not isinstance(self._name, str):
312 raise TypeError('method name must be a string')
Antoine Pitroua85017f2013-04-20 19:21:44 +0200313 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
Serhiy Storchaka35ac5f82015-05-20 18:29:18 +0300319 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
Antoine Pitroua85017f2013-04-20 19:21:44 +0200335# 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
Benjamin Petersond51374e2014-04-09 23:55:56 -0400375def imatmul(a, b):
376 "Same as a @= b."
377 a @= b
378 return a
379
Antoine Pitroua85017f2013-04-20 19:21:44 +0200380def 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 *
Brett Cannoncd171c82013-07-04 17:43:24 -0400413except ImportError:
Antoine Pitroua85017f2013-04-20 19:21:44 +0200414 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
Benjamin Petersond51374e2014-04-09 23:55:56 -0400437__matmul__ = matmul
Antoine Pitroua85017f2013-04-20 19:21:44 +0200438__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
Benjamin Petersond51374e2014-04-09 23:55:56 -0400458__imatmul__ = imatmul
Antoine Pitroua85017f2013-04-20 19:21:44 +0200459__ior__ = ior
460__ipow__ = ipow
461__irshift__ = irshift
462__isub__ = isub
463__itruediv__ = itruediv
464__ixor__ = ixor