导论
首先,回顾下闭包的概念:返回函数
然后看下这篇文章里的例子: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)
通过绑定默认参数,把指向外部环境的动态变量(随着for循环进行一直在变化)固定住,类似于"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': '派'}
希望通过一个循环,把字典里的value由str转变为匹配指定字符串行首字符是不是该str的函数。
比如,希望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()}
网友评论