Python中cell对象存储的是局部变量的值还是其引用?
Python闭包cell对象存储逻辑解释
Python官方文档对cell对象的描述翻译如下:「对于每个这类变量,解释器会创建一个cell对象来存储它的值;每个引用了该值的栈帧的本地变量中,都保存了对同样使用该变量的外层作用域的cell对象的引用。」
你对文档的误解核心在于对Python变量存储逻辑的认知:Python中所有的变量本质上都是存储对象的引用,不存在直接存储值拷贝的变量,cell对象的存储逻辑也符合这个规则。
你给出的测试代码运行逻辑完全符合cell的设计:
def func(): l = [1,2,3] def g(): print(l) return l,g l,g = func() l[0]=-1 g()
输出[-1, 2, 3]的原因可以拆解为以下几步:
func执行时首先创建列表对象[1,2,3],func作用域内的本地变量l存储的是这个列表对象的引用- 由于内层函数
g引用了外层作用域的l,解释器为变量l创建对应的cell对象,cell对象中存储的不是列表的拷贝,而是该列表对象的引用 func返回的第一个值就是本地变量l持有的列表引用,赋值给全局作用域的变量l- 执行
l[0]=-1时,是通过全局l持有的引用直接修改原列表对象的内部元素,没有改变l本身的引用指向 - 调用
g()时,内层函数从关联的cell对象中拿到的还是同一个列表对象的引用,打印结果自然是修改后的内容
你可以通过补充测试验证这个逻辑:如果执行l = [4,5,6]修改全局l的引用指向,再调用g(),打印的还是原来的[-1, 2, 3],因为你修改的只是全局变量l的引用,没有改变cell对象中存储的原列表引用。
总结:官方文档中的「存储值」是通用通俗表述,实际cell对象存储的是原变量指向的对象的引用,不会对指向的对象做深拷贝或浅拷贝,所以对可变对象的内容修改会在所有持有该引用的地方同步生效。
内容的提问来源于stack exchange,提问作者Rylan Liu
相关产品推荐
相关产品推荐

