2013-01-25 58 views
4
l = [1, 2, 3] 
a,b,c = [lambda: n*n for n in l] 
a() #=> 9 
b() #=> 9 
c() #=> 9 

這是爲什麼?我期望a(),b(),c()是1,4和9.在詞典理解中受到詞彙封閉困惑

+1

[在Python古怪的封閉行爲]的可能重複(http://stackoverflow.com/questions/11109838/weird-closure-behavior-in-python) –

+0

在迭代結束時'n'的值是3,而你實際上使用了全局變量'n'在你的lambda中。所以,每次你調用一個(),b()或c()時,他們都會尋找一個全局變量'n'。迭代後嘗試'del n',然後調用(),b()或c()。 –

+0

@AshwiniChaudhary - 小心點。在python3.x中,當你嘗試'del n'時(假設它以前沒有定義過...),你會得到一個'NameError'。但你對python2.x會發生什麼是正確的... – mgilson

回答

8

n不在函數的本地關閉中。

嘗試

a, b, c = [lambda n=n: n*n for n in l] 

此默認參數的「濫用」使每個功能

這裏可以創建一個名爲n一個局部變量是另一種方式在Python2

>>> L=[1, 2, 3] 
>>> def fgen(): 
...  local_n = global_n 
...  def f(): 
...   return local_n * local_n 
...  return f 
>>> a, b, c = [fgen() for global_n in L] 
>>> a() 
1 
>>> b() 
4 
>>> c() 
9 
創建一個封閉

它不會在Python3中工作,因爲列表理解中的循環變量不會泄漏到全局範圍內

Python3確實阻止我們在功能使用全局的一個更好的工作,所以你需要傳遞一個參數,如果你想用一個列表理解

>>> L=[1, 2, 3] 
>>> def fgen(param_n): 
...  local_n = param_n 
...  def f(): 
...   return local_n * local_n 
...  return f 
... 
>>> a, b, c = [fgen(n) for n in L] 
>>> a() 
1 
>>> b() 
4 
>>> c() 
9 
>>> 
+1

類似這樣的'[lambda x = n:x * x for n in l]'不太令人困惑。 –