python 闭包,可变参数

导论

首先,回顾下闭包的概念:返回函数

然后看下这篇文章里的例子: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()}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,079评论 19 139
  • 两本不错的书: 《Python参考手册》:对Python各个标准模块,特性介绍的比较详细。 《Python核心编程...
    静熙老师哈哈哈阅读 3,390评论 0 80
  • 要点: 函数式编程:注意不是“函数编程”,多了一个“式” 模块:如何使用模块 面向对象编程:面向对象的概念、属性、...
    victorsungo阅读 1,606评论 0 6
  • 本章将会介绍 闭包表达式尾随闭包值捕获闭包是引用类型逃逸闭包自动闭包枚举语法使用Switch语句匹配枚举值关联值原...
    寒桥阅读 1,580评论 0 3
  • 86.复合 Cases 共享相同代码块的多个switch 分支 分支可以合并, 写在分支后用逗号分开。如果任何模式...
    无沣阅读 1,455评论 1 5