-
Notifications
You must be signed in to change notification settings - Fork 222
/
lazy.py
49 lines (40 loc) · 1.57 KB
/
lazy.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
__all__ = ['Evaluable']
class Evaluable(object):
"""
A mixin class for types inherited from SymPy that may carry nested
unevaluated arguments.
This mixin is used to implement lazy evaluation of expressions.
"""
@classmethod
def _evaluate_maybe_nested(cls, maybe_evaluable):
if isinstance(maybe_evaluable, Evaluable):
return maybe_evaluable.evaluate
try:
# Not an Evaluable, but some Evaluables may still be hidden within `args`
if maybe_evaluable.args:
args = [Evaluable._evaluate_maybe_nested(i) for i in maybe_evaluable.args]
evaluate = not all(i is j for i, j in zip(args, maybe_evaluable.args))
try:
return maybe_evaluable.func(*args, evaluate=evaluate)
except TypeError:
# Not all objects support the `evaluate` kwarg
return maybe_evaluable.func(*args)
else:
return maybe_evaluable
except AttributeError:
# No `args` to be visited
return maybe_evaluable
@property
def args(self):
return ()
@property
def func(self):
return self.__class__
def _evaluate_args(self):
return [Evaluable._evaluate_maybe_nested(i) for i in self.args]
@property
def evaluate(self):
"""Return a new object from the evaluation of ``self``."""
args = self._evaluate_args()
evaluate = not all(i is j for i, j in zip(args, self.args))
return self.func(*args, evaluate=evaluate)