# Python变量保存的是什么?变量、对象和引用有什么关系?
面试官问:“Python的变量里保存的是什么?a = b之后,修改b会影响a吗?”
很多录友会套用C语言的理解:变量是一块内存,赋值就是把值拷进去。用这个模型看Python,很快会遇到解释不了的现象,比如改了一个列表,另一个变量也跟着变。这道题要讲清楚的是:Python变量是名字,对象才是数据,赋值是在名字和对象之间建立绑定。
# 简要回答
Python中,变量是一个名字,它保存的是对某个对象的引用,而不是对象本身。对象是真正存在于内存中的数据,有自己的身份、类型和值。
执行a = b时,Python不会复制对象,而是让名字a也绑定到b当前指向的对象。之后如果通过b原地修改这个对象,比如对列表append(),a看到的也是修改后的结果;如果是让b重新绑定到别的对象,比如b = [],a不受影响。
所以,“修改b会不会影响a”,要先分清这是修改对象,还是让名字指向新对象。
# 详细回答
# 赋值做了什么:先有对象,再绑定名字
执行赋值语句时,Python先计算右侧表达式,得到一个对象,再把左侧的名字绑定到这个对象上:
price = 100
discount = price
price = 80
print(discount) # 100
2
3
4
第一行,名字price绑定到整数对象100。第二行,discount绑定到price当前指向的同一个对象。第三行,price改为绑定整数对象80,discount仍然指向100。
赋值只改变名字的指向,不会修改原对象。 这也是为什么Python的名字没有固定类型:price可以先指向整数,再指向字符串,类型属于对象,不属于变量。

图左边是名字所在的命名空间,右边是对象。上半部分的重新绑定只改了箭头;下半部分的原地修改改的是对象,所以两个名字都能看到变化。
# 多个名字共享同一个可变对象
当共享的是可变对象时,绑定模型的影响就很明显:
cart = ["book"]
saved = cart
saved.append("pen")
print(cart) # ['book', 'pen']
print(cart is saved) # True
2
3
4
5
saved = cart没有生成新列表,cart和saved是同一个列表的两个名字。append()在原列表上添加元素,所以通过cart也能看到"pen"。is返回True,证明它们是同一个对象。
如果想要一个独立的列表,需要显式创建新对象,比如saved = cart.copy()或saved = list(cart)。
# 对象的三要素:身份、类型和值
每个对象都有三样东西:
身份:对象在生命周期内唯一且不变的标识,用id()查看,用is比较。在CPython中,id()返回的是对象的内存地址,但语言只保证它在对象存活期间唯一。
类型:决定对象支持哪些操作,用type()查看,创建后不会改变。
值:对象保存的数据。可变对象的值可以改,不可变对象的值不能改,这部分展开见《Python中的可变对象和不可变对象有什么区别?》。
名字本身不属于这三要素。同一个对象可以有零个、一个或多个名字指向它。
# del删除的是名字,不是对象
很多人以为del会直接销毁对象,其实它解除的是名字的绑定:
item = ["x"]
other = item
del item
print(other) # ['x']
2
3
4
del item之后,名字item不再可用,但列表还被other引用,所以对象依然存在。对象什么时候被回收,由解释器的内存管理决定;在CPython中,主要依靠引用计数,当没有任何引用指向对象时,它会被回收。
# 知识拓展
面试官可能追问:
Q1:Python函数传参是值传递还是引用传递?
两个说法都不够准确,更准确的叫法是对象共享传递:调用函数时,形参绑定到实参指向的同一个对象。函数内原地修改可变对象会影响外部,重新绑定形参则不会。它和本文讲的赋值绑定是同一套规则。
Q2:a is b和a == b有什么区别?
is判断两个名字是否指向同一个对象,==判断两个对象的值是否相等。值相等的两个列表可以是不同对象。具体规则和常见误用见《is和==有什么区别?》。
Q3:为什么a = 256; b = 256时a is b可能是True?
在CPython中,-5到256的小整数会被预先创建并复用,所以两个名字可能指向同一个对象。这是实现层面的优化,换一个版本或实现结果可能不同。比较数值应该用==,不能依赖这种缓存。
Q4:Python代码运行时,名字存在哪里?
名字存在命名空间中,比如模块的全局命名空间、函数调用时的局部命名空间,可以近似理解为“名字到对象”的映射。代码在执行前会被编译成字节码,执行过程见《Python程序如何运行?》。
评论
验证登录状态...