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', 'call', '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_none', 'is_not', 'is_not_none', 'isub', 'itemgetter', 'itruediv',
18
'ixor', 'le', '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
def is_none(a):
70
"Same as a is None."
71
return a is None
72

73
def is_not_none(a):
74
"Same as a is not None."
75
return a is not None
76

77
# Mathematical/Bitwise Operations *********************************************#
78

79
def abs(a):
80
"Same as abs(a)."
81
return _abs(a)
82

83
def add(a, b):
84
"Same as a + b."
85
return a + b
86

87
def and_(a, b):
88
"Same as a & b."
89
return a & b
90

91
def floordiv(a, b):
92
"Same as a // b."
93
return a // b
94

95
def index(a):
96
"Same as a.__index__()."
97
return a.__index__()
98

99
def inv(a):
100
"Same as ~a."
101
return ~a
102
invert = inv
103

104
def lshift(a, b):
105
"Same as a << b."
106
return a << b
107

108
def mod(a, b):
109
"Same as a % b."
110
return a % b
111

112
def mul(a, b):
113
"Same as a * b."
114
return a * b
115

116
def matmul(a, b):
117
"Same as a @ b."
118
return a @ b
119

120
def neg(a):
121
"Same as -a."
122
return -a
123

124
def or_(a, b):
125
"Same as a | b."
126
return a | b
127

128
def pos(a):
129
"Same as +a."
130
return +a
131

132
def pow(a, b):
133
"Same as a ** b."
134
return a ** b
135

136
def rshift(a, b):
137
"Same as a >> b."
138
return a >> b
139

140
def sub(a, b):
141
"Same as a - b."
142
return a - b
143

144
def truediv(a, b):
145
"Same as a / b."
146
return a / b
147

148
def xor(a, b):
149
"Same as a ^ b."
150
return a ^ b
151

152
# Sequence Operations *********************************************************#
153

154
def concat(a, b):
155
"Same as a + b, for a and b sequences."
156
if not hasattr(a, '__getitem__'):
157
msg = "'%s' object can't be concatenated" % type(a).__name__
158
raise TypeError(msg)
159
return a + b
160

161
def contains(a, b):
162
"Same as b in a (note reversed operands)."
163
return b in a
164

165
def countOf(a, b):
166
"Return the number of items in a which are, or which equal, b."
167
count = 0
168
for i in a:
169
if i is b or i == b:
170
count += 1
171
return count
172

173
def delitem(a, b):
174
"Same as del a[b]."
175
del a[b]
176

177
def getitem(a, b):
178
"Same as a[b]."
179
return a[b]
180

181
def indexOf(a, b):
182
"Return the first index of b in a."
183
for i, j in enumerate(a):
184
if j is b or j == b:
185
return i
186
else:
187
raise ValueError('sequence.index(x): x not in sequence')
188

189
def setitem(a, b, c):
190
"Same as a[b] = c."
191
a[b] = c
192

193
def length_hint(obj, default=0):
194
"""
195
Return an estimate of the number of items in obj.
196
This is useful for presizing containers when building from an iterable.
197

198
If the object supports len(), the result will be exact. Otherwise, it may
199
over- or under-estimate by an arbitrary amount. The result will be an
200
integer >= 0.
201
"""
202
if not isinstance(default, int):
203
msg = ("'%s' object cannot be interpreted as an integer" %
204
type(default).__name__)
205
raise TypeError(msg)
206

207
try:
208
return len(obj)
209
except TypeError:
210
pass
211

212
try:
213
hint = type(obj).__length_hint__
214
except AttributeError:
215
return default
216

217
try:
218
val = hint(obj)
219
except TypeError:
220
return default
221
if val is NotImplemented:
222
return default
223
if not isinstance(val, int):
224
msg = ('__length_hint__ must be integer, not %s' %
225
type(val).__name__)
226
raise TypeError(msg)
227
if val < 0:
228
msg = '__length_hint__() should return >= 0'
229
raise ValueError(msg)
230
return val
231

232
# Other Operations ************************************************************#
233

234
def call(obj, /, *args, **kwargs):
235
"""Same as obj(*args, **kwargs)."""
236
return obj(*args, **kwargs)
237

238
# Generalized Lookup Objects **************************************************#
239

240
class attrgetter:
241
"""
242
Return a callable object that fetches the given attribute(s) from its operand.
243
After f = attrgetter('name'), the call f(r) returns r.name.
244
After g = attrgetter('name', 'date'), the call g(r) returns (r.name, r.date).
245
After h = attrgetter('name.first', 'name.last'), the call h(r) returns
246
(r.name.first, r.name.last).
247
"""
248
__slots__ = ('_attrs', '_call')
249

250
def __init__(self, attr, /, *attrs):
251
if not attrs:
252
if not isinstance(attr, str):
253
raise TypeError('attribute name must be a string')
254
self._attrs = (attr,)
255
names = attr.split('.')
256
def func(obj):
257
for name in names:
258
obj = getattr(obj, name)
259
return obj
260
self._call = func
261
else:
262
self._attrs = (attr,) + attrs
263
getters = tuple(map(attrgetter, self._attrs))
264
def func(obj):
265
return tuple(getter(obj) for getter in getters)
266
self._call = func
267

268
def __call__(self, obj, /):
269
return self._call(obj)
270

271
def __repr__(self):
272
return '%s.%s(%s)' % (self.__class__.__module__,
273
self.__class__.__qualname__,
274
', '.join(map(repr, self._attrs)))
275

276
def __reduce__(self):
277
return self.__class__, self._attrs
278

279
class itemgetter:
280
"""
281
Return a callable object that fetches the given item(s) from its operand.
282
After f = itemgetter(2), the call f(r) returns r[2].
283
After g = itemgetter(2, 5, 3), the call g(r) returns (r[2], r[5], r[3])
284
"""
285
__slots__ = ('_items', '_call')
286

287
def __init__(self, item, /, *items):
288
if not items:
289
self._items = (item,)
290
def func(obj):
291
return obj[item]
292
self._call = func
293
else:
294
self._items = items = (item,) + items
295
def func(obj):
296
return tuple(obj[i] for i in items)
297
self._call = func
298

299
def __call__(self, obj, /):
300
return self._call(obj)
301

302
def __repr__(self):
303
return '%s.%s(%s)' % (self.__class__.__module__,
304
self.__class__.__name__,
305
', '.join(map(repr, self._items)))
306

307
def __reduce__(self):
308
return self.__class__, self._items
309

310
class methodcaller:
311
"""
312
Return a callable object that calls the given method on its operand.
313
After f = methodcaller('name'), the call f(r) returns r.name().
314
After g = methodcaller('name', 'date', foo=1), the call g(r) returns
315
r.name('date', foo=1).
316
"""
317
__slots__ = ('_name', '_args', '_kwargs')
318

319
def __init__(self, name, /, *args, **kwargs):
320
self._name = name
321
if not isinstance(self._name, str):
322
raise TypeError('method name must be a string')
323
self._args = args
324
self._kwargs = kwargs
325

326
def __call__(self, obj, /):
327
return getattr(obj, self._name)(*self._args, **self._kwargs)
328

329
def __repr__(self):
330
args = [repr(self._name)]
331
args.extend(map(repr, self._args))
332
args.extend('%s=%r' % (k, v) for k, v in self._kwargs.items())
333
return '%s.%s(%s)' % (self.__class__.__module__,
334
self.__class__.__name__,
335
', '.join(args))
336

337
def __reduce__(self):
338
if not self._kwargs:
339
return self.__class__, (self._name,) + self._args
340
else:
341
from functools import partial
342
return partial(self.__class__, self._name, **self._kwargs), self._args
343

344

345
# In-place Operations *********************************************************#
346

347
def iadd(a, b):
348
"Same as a += b."
349
a += b
350
return a
351

352
def iand(a, b):
353
"Same as a &= b."
354
a &= b
355
return a
356

357
def iconcat(a, b):
358
"Same as a += b, for a and b sequences."
359
if not hasattr(a, '__getitem__'):
360
msg = "'%s' object can't be concatenated" % type(a).__name__
361
raise TypeError(msg)
362
a += b
363
return a
364

365
def ifloordiv(a, b):
366
"Same as a //= b."
367
a //= b
368
return a
369

370
def ilshift(a, b):
371
"Same as a <<= b."
372
a <<= b
373
return a
374

375
def imod(a, b):
376
"Same as a %= b."
377
a %= b
378
return a
379

380
def imul(a, b):
381
"Same as a *= b."
382
a *= b
383
return a
384

385
def imatmul(a, b):
386
"Same as a @= b."
387
a @= b
388
return a
389

390
def ior(a, b):
391
"Same as a |= b."
392
a |= b
393
return a
394

395
def ipow(a, b):
396
"Same as a **= b."
397
a **=b
398
return a
399

400
def irshift(a, b):
401
"Same as a >>= b."
402
a >>= b
403
return a
404

405
def isub(a, b):
406
"Same as a -= b."
407
a -= b
408
return a
409

410
def itruediv(a, b):
411
"Same as a /= b."
412
a /= b
413
return a
414

415
def ixor(a, b):
416
"Same as a ^= b."
417
a ^= b
418
return a
419

420

421
try:
422
from _operator import *
423
except ImportError:
424
pass
425
else:
426
from _operator import __doc__ # noqa: F401
427

428
# All of these "__func__ = func" assignments have to happen after importing
429
# from _operator to make sure they're set to the right function
430
# __lt__ = lt
431
# __le__ = le
432
# __eq__ = eq
433
# __ne__ = ne
434
# __ge__ = ge
435
# __gt__ = gt
436
# __not__ = not_
437
# __abs__ = abs
438
# __add__ = add
439
# __and__ = and_
440
# __call__ = call
441
# __floordiv__ = floordiv
442
# __index__ = index
443
# __inv__ = inv
444
# __invert__ = invert
445
# __lshift__ = lshift
446
# __mod__ = mod
447
# __mul__ = mul
448
# __matmul__ = matmul
449
# __neg__ = neg
450
# __or__ = or_
451
# __pos__ = pos
452
# __pow__ = pow
453
# __rshift__ = rshift
454
# __sub__ = sub
455
# __truediv__ = truediv
456
# __xor__ = xor
457
# __concat__ = concat
458
# __contains__ = contains
459
# __delitem__ = delitem
460
# __getitem__ = getitem
461
# __setitem__ = setitem
462
# __iadd__ = iadd
463
# __iand__ = iand
464
# __iconcat__ = iconcat
465
# __ifloordiv__ = ifloordiv
466
# __ilshift__ = ilshift
467
# __imod__ = imod
468
# __imul__ = imul
469
# __imatmul__ = imatmul
470
# __ior__ = ior
471
# __ipow__ = ipow
472
# __irshift__ = irshift
473
# __isub__ = isub
474
# __itruediv__ = itruediv
475
# __ixor__ = ixor

0

WPM •0 •0

100%

ACC •0 •0

0s

TIME •0