Python中的late binding(延迟绑定)问题

延迟绑定

在Python中存在这样的一种机制,即函数或闭包中的变量值只有在函数或闭包中的内部函数执行的时候才会进行查找赋值。
下面通过一个小例子来说明这种情况:

def create_multiplier():
    return [lambda x : x*i for i in range(3)]

for func in create_multiplier():
    print(func(2))

其实写这段代码的人最初的想法是通过这么一个函数来创建多个函数,分别使用对应的函数来实现对应的功能,所以他会认为上面的代码输出的结果应该是0, 2, 4,但是实际情况并非如此,真实的结果是4,4,4。
下面我们来分析一下出现上述结果的原因,由于在上述代码中的列表推导式中,匿名函数使用到了后面for循环表达式中的i值,相当于这个内部(匿名)函数使用到了闭包(enclosing)create_multiplier函数中的局部变量,这种情况下,匿名函数中使用到的这个参数只会在这个内部函数被调用时才会去闭包中查找,而此时闭包中的for循环已经结束,变量i的值为2,所以此时所有被创建出的函数被调用时使用的参数值都为2。
那么问题来了,如何实现写这段代码的人的最初的想法呢?
我们可以利用给内部函数设置默认参数的方式,动态的去获取闭包中局部变量的值:

def create_multiplier():  
    return [lambda x, i=i : x * i for i in range(3)]

for func in create_multiplier():
    print(func(2))

此时代码的运行结果为:0, 2, 4

猜你喜欢

转载自blog.csdn.net/june_young_fan/article/details/80606914