導論
首先,回顧下閉包的概念:返回函數
然后看下這篇文章里的例子:Default Parameter Values in Python
注意到叶组,
for i in range(10):
def callback():
print "clicked button", i
UI.Button("button %s" % i, callback)
only to find that all callbacks print the same value (most likely 9, in this case). The reason for this is that Python’s nested scopes bind to variables, not object values, so all callback instances will see the current (=last) value of the “i” variable. To fix this, use explicit binding:
有兩種思路來解決:綁定默認參數拯田,構建閉包。
綁定默認參數
for i in range(10):
def callback(i=i):
print "clicked button", i
UI.Button("button %s" % i, callback)
通過綁定默認參數甩十,把指向外部環(huán)境的動態(tài)變量(隨著for循環(huán)進行一直在變化)固定住船庇,類似于"take a snapshot"。
接下來枣氧,如果需要向callback
傳遞別的參數怎么辦溢十?
方案:
for i in range(10):
def callback(my_str, i=i):
print my_str, i
UI.Button("button %s" % i, callback)
閉包
for i in range(10):
def closure()
def callback():
print "clicked button", i
return callback
UI.Button("button %s" % i, closure())
這里,因為closure()
函數在返回另一個函數callback
時达吞,需要將運行callback()
所需的local variables都封裝好张弛,形成一個閉包,所以i
的值被固定下來作為閉包的一部分一起返回酪劫。
應用
給定一個字典
character_start = {'examples': '例',
'syns': '近',
'ants': '反',
'der': '派'}
希望通過一個循環(huán)吞鸭,把字典里的value由str轉變?yōu)槠ヅ渲付ㄗ址惺鬃址遣皇窃搒tr的函數。
比如覆糟,希望examples
里存放的是一個判斷行首字符是否為例
的函數刻剥。該函數接受一個字符串作為輸入,根據判斷結果返回True
或者False
滩字。
不正確的實現方式:
incorrect_implement_character_start = {key: lambda s: s[0] == value.decode('utf-8') for key, value in character_start.iteritems()}
# pitfall: value is a global variable and is dynamically changing,
# so finally all lambda's will refer to the last value, in this case it is the value of syns!
閉包 實現
for key, value in character_start.iteritems():
def gen_match_fun_closure(_value):
return lambda s: s[0] == _value.decode('utf-8')
character_start[key] = gen_match_fun_closure(value)
綁定默認參數 實現
corrent_implement_character_start = {key: lambda (s, _value=value): s[0] == _value.decode('utf-8') for key, value in character_start.iteritems()}