2013-01-08 92 views
2

我搜索了並且找不到我的問題的直接答案,所以如果已經發布/回答了此問題,請致歉。我正在使用python,我需要傳遞包含變量的表達式,但我不希望它們被立即評估。在python中傳遞算術表達式而不評估它們

例如:

r = x*y 

我希望程序要記住,爲了計算R,它需要乘以X和Y,而不是在當時明確地計算它。我試過使用:

x = None 
y = None 
r = x*y 

但是這不允許對變量進行操作。我已經使用字符串管理它,然後使用「eval」,但它不是一個非常優雅的解決方案,而且它也非常緩慢。有沒有更好的方法來做到這一點?

+3

您是否嘗試過lambda表達式(實際上是函數對象)? – martineau

+0

我在一年前問了一個非常類似的問題,並得到了[這個最優秀的答案](http://stackoverflow.com/a/7844038/566644),它得到了少得多的票比它應得的。 –

+0

這裏你真正的目標是什麼?如果你能告訴我們,我認爲會有更清潔的解決方案。我認爲你有一個設計問題,而不是一個python問題。 – Ber

回答

4

你可以使用一個lambda表達:

>>> 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 

你甚至可以得到多一點花哨的類:

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 

與輸出:

Oops, can't calculate r yet -- Reason: unsupported operand type(s) for *: 'NoneType' and 'NoneType' 
3 
3 

當然,如果你想做的事情不需要,在這裏你需要添加更多的方法加法,減法,... 當然,那麼你必須實際上致電r爲了得到你的結果 - 但這不是很糟糕嗎?

+0

我愛一個很好的lambda – ckb

+0

非常感謝您的幫助,它非常有用。我還需要能夠編輯這些表達式,我認爲這不可能使用lambda表達式,但是您的類的例子爲我們提供了許多想法。乾杯。 –

+0

@NathanBush - 你是什麼意思「編輯」的表達?你總是可以用新的替換它:'r = lambda:x + y'。 – mgilson

0

您可以查看Math Evaluator實用程序的source code以瞭解如何在稍後創建用於評估的表達式。 Ideone.com上的demonstration有助於顯示代碼的完成情況。

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']