2011-06-19 63 views
3

我有一些昂貴的函數f(x),我只想計算一次,但被稱爲相當頻繁。從本質上講,第一次調用函數時,它應該計算一系列x值的一大堆值,因爲它將被整合,然後用樣條插值,並以某種方式緩存係數,可能在文件中進一步使用。Python:從函數內重新定義函數

我的想法是做類似下面的事情,因爲它很容易實現。第一次調用函數時,它會執行某些操作,然後重新定義自己,然後再執行其他操作。然而,它並不像預期的那樣工作,並且通常可能是不好的做法。

def f(): 
    def g(): 
     print(2) 
    print(1) 
    f = g 
f() 
f() 

預期輸出:

1 
2 

實際輸出:

1 
1 

定義克F()以外()沒有幫助。爲什麼這不起作用?除此之外,我現在能想到的唯一解決方案是使用一些全局變量。或者爲此寫一個類是否有意義?

回答

6

這太複雜了。相反,使用記憶化:

def memoized(f): 
    res = [] 
    def resf(): 
     if len(res) == 0 
      res.append(f()) 
     return res[0] 
    return resf 

,然後簡單地

@memoized 
def f(): 
    # expensive calculation here ... 
    return calculated_value 

在Python 3,你可以用functools.lru_cache取代memoized

+0

+1:[memoization](http://en.wikipedia.org/wiki/Memoization)和[裝飾](http://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators),允許裝飾的Python版本,是要走的路。規範示例[這裏](http://wiki.python.org/moin/PythonDecoratorLibrary#Memoize)。 – Johnsyweb

+0

難道你不知道字典是不可能的嗎? – juanchopanza

+0

@juanchopanza哎呀,是的。刪除了參數,因爲無論如何它們在這個示例中都是不必要的。 – phihag

3

更改F IN F公司範圍不功能之外的影響,如果你想改變男,你可以使用全局:

>>> def f(): 
...  print(1) 
...  global f 
...  f=lambda: print(2) 
... 
>>> f() 
1 
>>> f() 
2 
>>> f() 
2 
1

什麼你所描述的那種問題緩存被髮明瞭。爲什麼不只是有一個緩衝區來保存結果;在進行昂貴的計算之前,檢查緩衝區是否已經填滿;如果是,則返回緩衝結果,否則執行計算,填充緩衝區,然後返回結果。無需爲自己修改代碼而喜歡它。

+0

他說出真相。阿門(+1)。 – jkp

5

只需在f函數的開頭添加global f,否則python會創建一個局部f變量。