我的意圖是創建一個字典,其中包含哪些鍵是基元,其值是否爲返回字符串的零參數函數。 (這是實施VM的較大項目的一部分。)這些功能中的某些功能並不重要,並且可以手動創建和分配。那些工作很好。然而,其他人似乎適合自動生成。如何強制python3傳遞值?
我第一次嘗試失敗:
>>> regs = ['a', 'b', 'c', 'x', 'y', 'z']
>>> vals = {i : lambda: r for i, r in enumerate(regs)}
>>> [(k, vals[k]()) for k in vals.keys()]
[(0, 'z'), (1, 'z'), (2, 'z'), (3, 'z'), (4, 'z'), (5, 'z')]
OK,罰款; lambda函數直到它被調用時纔讀取r。我再次嘗試,試圖找出自身的價值:
>>> from copy import copy
>>> vals = {}
>>> i = 0
>>> for reg in regs:
... r = copy(reg) # (1)
... vals[i] = lambda: r
... i += 1
...
>>> [(k, vals[k]()) for k in vals.keys()]
[(0, 'z'), (1, 'z'), (2, 'z'), (3, 'z'), (4, 'z'), (5, 'z')]
(1)我想這一步就創建在REG這樣做不會改變一個獨立的變量。事實證明,情況並非如此。
這樣的嘗試顯然沒有奏效。也許複製一個字符串是一個noop?
>>> 's' is 's'
True
>>> a = 's'
>>> b = copy(a)
>>> a is b
True
>>> from copy import deepcopy
>>> b = deepcopy(a)
>>> a is b
True
對。複製一個字符串,是一個noop。深度複製不能解決這個問題。結果,lambda仍然引用了每個循環中正在更新的變量,從而導致此錯誤。
我們需要一種不同的方法。如果我將變量保存到臨時函數的靜態變量,該怎麼辦?如果每個臨時功能都有自己的標識,那麼這應該起作用...
>>> vals = {}
>>> i = 0
>>> for reg in regs:
... def t():
... return t.r
... t.r = reg
... vals[i] = t
... i += 1
...
>>> [(k, vals[k]()) for k in vals.keys()]
[(0, 'z'), (1, 'z'), (2, 'z'), (3, 'z'), (4, 'z'), (5, 'z')]
沒有。此時,我正在手動處理所有這些:
>>> vals = {}
>>> vals[0] = lambda: 'a'
>>> vals[1] = lambda: 'b'
...等等。這感覺就像是放棄了,而且會令人難以置信的乏味。是否有合適的pythonic方式來完成這項任務?畢竟,我通常喜歡python的原因之一是我遠離手動指針管理;我從未想到我希望它包含一整套指針工具!
謝謝!設置默認參數對於我來說比通過make_const函數提供所有內容更重要,至少就我對它的工作原理的理解而言。我不認爲這兩種方法在性能上有任何顯着差異? – coriolinus 2012-04-06 12:08:07
@coriolinus不應有任何顯着差異。如果有的話,在成爲瓶頸之前可能有很多大的魚要炒。在這一點上,你可能應該咬緊牙關,讓你的代碼[RPython](http://morepypy.blogspot.de/2011/04/tutorial-writing-interpreter-with-pypy.html),然後編譯C,一個JIT編譯器和一系列好的GC幾乎免費。 – delnan 2012-04-06 12:37:50