Python规避closure late binding后输出不符合预期的问题咨询
问题核心原因解答
你遇到的现象和闭包、迟绑定没有关联,本质是Python可变对象的引用传递特性导致的。
常见误区纠正
- 你提供的第一段代码中的
my_func不属于闭包:闭包的定义是嵌套定义、且引用了外层非全局作用域自由变量的函数,你的my_func是顶层函数,引用的是全局作用域的array和path,完全不满足闭包的定义,你最初对问题原因的判断有误。 - 第二段代码已经消除了自由变量,也确实不是闭包,但问题没有解决的原因是你没有命中问题的核心根源。
核心原理说明
列表属于Python中的可变对象,你执行array.append(path)操作时,追加到array中的不是path当前的内容副本,而是path这个列表对象的内存引用:
- 两次循环中你操作的都是同一个
path列表对象,第一次循环后path为[0],array里存入了这个对象的引用 - 第二次循环你给同一个
path追加了1,path变成[0,1],此时array里的第一个元素因为指向同一个对象,内容也会同步变化 - 最终
array里两个元素都指向最终值为[0,1]的同一个列表,所以输出为[[0, 1], [0, 1]]
解决方法
如果要存入path每次迭代的快照,只需要在追加时存入它的浅拷贝即可,列表的浅拷贝可以用copy()方法或者切片语法[:],修改后代码如下:
def my_func(array, path): # 追加path的浅拷贝,而非原对象的引用 array.append(path.copy()) return array, path = [], [] for value in range(2): path.append(value) my_func(array, path) print(array) # 输出为预期的[[0], [0, 1]]
内容的提问来源于stack exchange,提问作者somaito
相关产品推荐
相关产品推荐

