You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中变量的identity(标识)在什么情况下会发生变化?

问题解答

你对Python官方文档的理解是正确的:对象一旦创建,标识(identity)就永远不会变。你遇到的疑问本质是混淆了「变量(引用)」和「对象」这两个完全不同的概念:Python里的变量只是绑定到对象上的标签,它本身不是对象,你给变量重新赋值,只是修改了标签绑定的对象,没有修改任何原有对象的标识。

你提供的测试代码如下:

a = 5

def fun(b):
  global a
  a = 5
  print(a, b) # 5, 5 
  print (a is b) # True

def foo(b):
  global a
  a = 6
  print(a, b) # 6, 5 
  print (a is b) # False

fun(a)
foo(a)

这里还需要先了解一个CPython的默认优化特性:小整数驻留机制。为了减少频繁创建销毁小整数的性能开销,CPython会把[-5, 256]范围内的所有整数提前创建好放到缓存池里,所有用到这个范围内相同值的整数,都会直接指向缓存池里的同一个对象,不会重复创建新对象。


为什么给变量a赋不同值时,它的标识会发生变化?

你观察到的「a的标识变化」,其实不是a原来指向的对象标识变了,是a = 新值这个操作,把a这个标签从原来绑定的对象上撕下来,绑定到了另一个新的对象上:

  • 初始执行a=5时,a绑定到缓存池里的5对象,此时用id(a)拿到的是这个5对象的标识
  • 后续执行a=6时,a被重新绑定到缓存池里的6对象,id(a)现在返回的是6对象的标识

原来的5对象一直都在缓存池里,它的标识从来没有变过,只是a不再指向它了而已。


两个函数中的赋值操作为什么会表现出不同的行为?

拆解两次函数调用的完整流程就能明确差异:

调用fun(a)时的执行逻辑

  • 调用前全局变量a绑定的是5对象,传参给b的操作相当于b = a,所以b也绑定到同一个5对象
  • 函数内声明使用全局a,执行a=5:因为5在小整数缓存池里,已经存在对应的对象,所以a还是绑定到原来的5对象,绑定关系没有变化
  • 此时a和b都指向同一个5对象,所以a is b返回True

调用foo(a)时的执行逻辑

  • 调用前全局变量a还是绑定的5对象,所以传参后b还是绑定到5对象
  • 函数内执行a=6:6对应的缓存对象和5的对象完全不同,所以全局a被重新绑定到6对象
  • 此时a指向6对象,b指向5对象,是两个完全不同的对象,所以a is b返回False

内容的提问来源于stack exchange,提问作者Vighnesh Nayak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 23:24:01