python 闭包,你必须知道的坑!

本文深入探讨Python中闭包的概念,解析闭包中循环变量的引用陷阱,以及如何正确处理循环变量以达到预期结果。
funcs = []
result_list = []
for x in range(3):
    def do_some():
        return x
    funcs.append(do_some)
    result_list.append(do_some())  # 注意这里函数被执行了

funcs_result_list = [func() for func in funcs]

很多人以为result_listfuncs_result_list的结果是一样的,都是[0, 1, 2],实际结果却大跌眼镜

print(result_list )       # [0, 1, 2]
print(funcs_result_list ) # [2, 2, 2]

为什么两者的结果不一样?

  1. 在闭包中,funcs.append(do_some) do_some函数并没有立即执行,而是以某种方式保存了下来, 即只返回函数的地址

  2. 在闭包作用域,Python的闭包是 迟绑定 , 这意味着闭包中用到的变量的值,是在内部函数被调用时查询得到的

  3. 当执行[func() for func in funcs], 内部函数do_some才真正被执行, 然而此时for循环已经被执行完毕,x的值不会再改变,都是2

如何改动代码,达到预期结果呢?
将循环变量作为命名变量传递给函数do_some即可

funcs = []
for x in range(3):
    def do_some(x=x):
        return x
    funcs.append(do_some)
 
funcs_result_list = [func() for func in funcs] 
print(funcs_result_list )       # [0, 1, 2]

为什么这样可行? 因为这会在函数内再次定义一个局部变量,不再依赖于for 循环中的x

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值