Reputation: 1461
I've searched and couldn't find a direct answer for my question, so apologies if this has already been posted/answered before. I'm working in python and i need to pass expressions that contain variables, but i don't want them to be immediately evaluated.
For example:
r = x*y
I want the program to remember that in order to calculate r, it needs to multiply x and y instead of explicitly calculating it at the time. I've tried using:
x = None
y = None
r = x*y
But this doesn't allow operations on the variables. I've managed it using strings and then using "eval" but its not a very elegant solution, and its also painfully slow. Is there a better way of doing this?
Upvotes: 2
Views: 760
Reputation: 22041
You might look at the source code of the Math Evaluator utility to get an idea how to create expressions for evaluation later on. This demonstration on Ideone.com helps to show what the code can accomplish.
if __name__ == '__main__':
# Run a simple demo that shows evaluator's capability.
namespace = {}
expression = tokens('x * y -> r')
print expression
evaluate('2 -> x; 3 -> y', namespace)
expression.evaluate(namespace)
print 'r =', namespace['r']
alternate = Operation(Operation(Variable('x'), '+', Variable('y')), '->', Variable('r'))
print alternate
alternate.evaluate(namespace)
print 'r =', namespace['r']
Upvotes: 0
Reputation: 310287
You could use a lambda
expression:
>>> x = None
>>> y = None
>>> r = lambda : x*y
>>> r()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
TypeError: unsupported operand type(s) for *: 'NoneType' and 'NoneType'
>>> x = 1
>>> y = 2
>>> r()
2
You could even get a little more fancy with a class:
class DeferredEval(object):
def __init__(self,func):
self.func = func
def __call__(self):
return self.func()
def __add__(self,other):
return self.func() + other
def __radd__(self,other):
return other + self.func()
x = None
y = None
r = DeferredEval(lambda:x*y)
try:
a = 1 + r
except TypeError as err:
print "Oops, can't calculate r yet -- Reason:",err
x = 1
y = 2
print 1 + r
print r + 1
with the output:
Oops, can't calculate r yet -- Reason: unsupported operand type(s) for *: 'NoneType' and 'NoneType'
3
3
Of course, here you'll need to add a whole bunch more methods if you want to do things that aren't addition, subtraction, ...
Of course, then you have to actually call r
in order to get your result -- but that's not so bad is it?
Upvotes: 4