Skip to content

Instantly share code, notes, and snippets.

@romeroyonatan
Created February 23, 2018 20:33
Show Gist options
  • Save romeroyonatan/6bab27b4d1d5e2d5e9a6f395ac1e1257 to your computer and use it in GitHub Desktop.
Save romeroyonatan/6bab27b4d1d5e2d5e9a6f395ac1e1257 to your computer and use it in GitHub Desktop.
Lazy chainable operator
import operator
class Operator(object):
'''Chaineable and lazy operations'''
def __init__(self, value, *args):
self._value = value
self._args = args
def value(self):
if callable(self._value):
return self._value(*map(Operator.resolve, self._args))
return self._value
@staticmethod
def resolve(arg):
if isinstance(arg, Operator):
return arg.value()
return arg
def __add__(self, value):
return Operator(operator.add, self, value)
def __radd__(self, value):
return Operator(operator.add, value, self)
def __sub__(self, value):
return Operator(operator.sub, self, value)
def __rsub__(self, value):
return Operator(operator.sub, value, self)
def __mul__(self, value):
return Operator(operator.mul, self, value)
def __rmul__(self, value):
return Operator(operator.mul, value, self)
def __div__(self, value):
return Operator(operator.div, self, value)
def __rdiv__(self, value):
return Operator(operator.div, value, self)
def __repr__(self):
if self._args:
return 'Operator(value=%r, args=%r)' % (self._value, self._args)
return 'Operator(%r)' % self._value
def __str__(self):
return str(self.value())
>>> from chain import Operator
>>> operators = [Operator(x) for x in range(10)]
>>> operators
[Operator(0), Operator(1), Operator(2), Operator(3), Operator(4), Operator(5), Operator(6), Operator(7), Operator(8), Operator(9)]
>>> sum(operators)
Operator(value=<built-in function add>, args=(Operator(value=<built-in function add>, args=(Operator(value=<built-in function add>, args=(Operator(value=<built-in function add>, args=(Operator(value=<built-in function add>, args=(Operator(value=<built-in function add>, args=(Operator(value=<built-in function add>, args=(Operator(value=<built-in function add>, args=(Operator(value=<built-in function add>, args=(Operator(value=<built-in function add>, args=(0, Operator(0))), Operator(1))), Operator(2))), Operator(3))), Operator(4))), Operator(5))), Operator(6))), Operator(7))), Operator(8))), Operator(9)))
>>> result=_
>>> result.value()
45
>>> result = Operator(1) + Operator(10) / Operator(5)
>>> result.value()
3
>>> result = Operator(1) + 10 / 5
>>> result.value()
3
>>> result = 1 + Operator(2)
>>> result.value()
3
>>> result = 1 + Operator(2) / 0
>>> result # Because operation is lazy, exception not raised
Operator(value=<built-in function add>, args=(1, Operator(value=<built-in function div>, args=(Operator(2), 0))))
>>> result.value()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "chain.py", line 13, in value
return self._value(*map(Operator.resolve, self._args))
File "chain.py", line 19, in resolve
return arg.value()
File "chain.py", line 13, in value
return self._value(*map(Operator.resolve, self._args))
ZeroDivisionError: integer division or modulo by zero
>>>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment