python 进阶之路:绑定延迟
看看下面一题,试着写出自己的答案。 def multipliers(): return [lambda x: i * x for i in range(4)] print([m(2) for m in multipliers()]) print(type(multipliers())) res: [6, 6, 6, 6] <class 'list'> 输出结果不是我们想的[0,2,4,6],这是为什么呢?如何输出我们想的结果呢? 首先,上述问题产生的原因是python 闭包的延迟绑定。在这里你可能会有疑问 ,什么是闭包? 在python 的核心编程里,闭包定义如下: 如果在一个内部函数里,对外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被 认定为闭包。 总结为三点: 1、是一个内嵌函数 2、对外部函数变量的引用 3、外部函数返回内嵌函数 简单的闭包eg: def counter(start_at=0): count = [start_at] def incr(): count[0] += 1 return count[0] return incr 继续刚才的问题,python 闭包的延迟绑定,意味着 内部函数被调用,时,参数的值在闭包内进行查找。因此, 当任何有multipliers()返回的函数被调用时,i 的值 将在附近范围进行查找。那是不管返回函数是否被调用,for 循环已经完成,i被赋予最终值3,因此,每次返回的函数乘以 传递过来的值3 ,因为上段代码传过来的值是2,他们最终的返回都是6。 以匿名函数的形式,看着你可能存在疑惑,现在为你转换成 for循环语句, 便于你理解。 def func(): fun_list = [] for i in range(4): def foo(x): return x*i fun_list.append(foo) return fun_list for m in func(): print m(2) 那现在考虑一下,如何输出我们想的结果【0,2,4,6】? 两种方法为您推荐: 方法一: def multipliers(): for i in range(4): yield lambda x: i * x print([m(2) for m in multipliers()]) print(type(multipliers())) res: [0, 2, 4, 6] <class 'generator'> 方法二: def multipliers(): return [lambda x, i=i: i * x for i in range(4)] print([m(2) for m in multipliers()]) print(type(multipliers())) res: [0, 2, 4, 6] <class 'list'>