导读:本期聚焦于小伙伴创作的《Python id()函数怎么用?获取对象内存地址与同一性比较详解》,敬请观看详情。在调试Python程序时,你是不是遇到过两个变量值相等却判断为不同对象的情况。这背后其实是对象身份在起作用。id()函数返回对象在其生命周期内的唯一整数标识,这个标识在CPython中恰好是对象的内存地址。通过id()可以直观查看变量是否指向同一块内存,从而区分值相等与同一性相等。本文说明id()的基本用法、返回值的含义,以及它与is运算符、等号比较之间的差异,并解释小整数池和字符串驻留等现象对id结果的影响,帮助你在比较对象和排查引用问题时准确使用它。

Python内置的id()函数用于返回对象的唯一标识符,在CPython解释器中这个标识符就是对象在内存中的地址。理解它对于掌握变量引用、对象生命周期以及同一性判断非常关键。很多初学者容易把值相等和对象相同混为一谈,而id()恰恰能提供最底层的视角。

Python id()函数怎么用?获取对象内存地址与同一性比较详解

id()函数的基本用法与返回值含义

id()的语法极其简单,它接受一个对象作为参数,返回该对象当前的唯一整数标识。在CPython实现中,这个整数就是对象在堆内存中的地址,因此你经常会看到不同对象的id值相差很大,而同一个对象在存活期间的id始终不变。需要注意的是,对象销毁后其id可能被后续新对象复用,所以不能把id当作跨生命周期的永久编号。

下面这段代码展示了如何用id()观察普通对象:

a = [1, 2, 3]
b = a
c = [1, 2, 3]
print(id(a))   # 输出a的标识
print(id(b))   # 与a相同,因为b引用同一对象
print(id(c))   # 与a不同,c是新列表对象
print(a is b)  # True
print(a is c)  # False

从输出可以看出,b = a只是把引用赋给b,两者指向同一个列表,因此id(a)id(b)完全一致;而c通过字面量新建列表,即便内容相同,也是另一个对象,id不同。这种机制解释了为什么修改a会影响b却不影响c

除了复合对象,不可变对象同样适用。比如整数和字符串,不过它们存在解释器层面的优化,我们后面会专门说明。总之,id()让你跳过值的比较,直接看到对象身份这一层。

id()与is运算符及等号比较的区别

不少开发者在判断两个变量关系时,会在==is之间犹豫。其实==比较的是值是否相等,由对象的__eq__方法决定;is比较的是对象同一性,本质上就是比较两者的id()是否相等;而id()本身只是把这种身份以整数形式暴露出来。因此a is b完全等价于id(a) == id(b)

看一个容易踩坑的例子:

x = 256
y = 256
print(x == y)      # True,值相等
print(x is y)      # True,小整数池内同一对象
print(id(x) == id(y))

m = 257
n = 257
print(m is n)      # 可能为False,超出小整数缓存
print(id(m) == id(n))  # 通常不同

这里涉及CPython的小整数对象池,区间[-5, 256]内的整数会被预先创建并复用,所以两个256字面量其实指向同一个对象,id相同;而257不在池内,每次出现都可能新建对象,导致id不同。用id()打印出来就能确认这一点,避免误以为is判断不可靠。

字符串也有类似的驻留机制,但并非所有字符串都驻留。短字符串或看起来像标识符的字符串往往共享,而动态拼接的长串通常独立。在需要确认两个字符串变量是否同一对象时,id()比猜测驻留规则更直观。不过生产代码中比较字符串内容仍应使用==,只有特定底层优化场景才用is配合id()验证。

利用id()排查引用问题与常见误区

在函数参数传递、容器嵌套等场景下,对象被多个变量引用是常态。当程序出现“改了A却影响了B”的诡异现象,用id()打印相关变量的标识,往往能快速定位是不是同一引用。例如在函数中修改传入的列表,外部也跟着变,这正是因为传参传的是引用,id一致。

一个典型误区的代码示例如下:

def append_val(lst, val):
    lst.append(val)

base = []
group = [base, base, base]
print([id(x) for x in group])  # 三个元素id相同
append_val(group[0], 10)
print(group)  # [[10], [10], [10]]

上面group列表里放了三个对同一base对象的引用,通过id()可以证明它们地址一样。修改其中一个,全部联动。如果不使用id()观察,很难意识到自己存的是引用而非拷贝。

另一个误区是认为id()返回的是对象内容的哈希。实际上默认hash()对可变对象不可用,而id()始终可用且不等于哈希值。还有人把id用于跨进程或持久化身份判断,这是错误的,因为不同进程内存布局独立,id只在单次运行内有意义。正确做法是业务层用唯一主键或uuid标识,而非依赖内存地址。

综上,id()是理解Python对象模型的显微镜。它不复杂,却能在引用纠缠、同一性判断、解释器优化验证等方面提供确凿证据。养成在可疑处打印id()的习惯,比单纯靠经验猜测要稳健得多。

Pythonid函数对象同一性修改时间:2026-08-13 21:27:33

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。