Python中对象身份和对象值到底有什么不同?

来源:AI教程网作者:勇士头衔:草根站长
导读:本期聚焦于小伙伴创作的《Python中对象身份和对象值到底有什么不同?》,敬请观看详情。把两个变量赋值成同样的内容,用等号比较却返回False,这种困惑大多来自没分清对象身份与对象值。对象身份是对象在内存中的唯一编号,由id函数返回,如同门牌号不可重复。对象值则是对象承载的数据内容,比如数字大小或字符串文本。is运算符判断身份是否一致,等于号判断值是否相等。小整数和短字符串有缓存机制,会让不同变量指向同一身份,干扰直觉判断。理解二者差异能避免比较逻辑错误,也能弄清参数传递时为何有时原对象被改动。

在Python编程中,每一个被创建出来的数据都是一个对象,而理解对象的身份与对象值之间的差异,是写出正确比较逻辑和避免隐蔽Bug的基础。对象身份相当于对象在内存中的“身份证号”,由解释器分配且在其生命周期内保持不变;对象值则是这个对象所表达的具体数据内容。很多初学者容易把“两个东西看起来一样”和“两个东西其实是同一个”混为一谈,从而导致使用is与等于号时出现意外结果。

Python中对象身份和对象值到底有什么不同?

一、对象身份的本质

对象身份指的是某个对象在内存中的唯一标识。在CPython实现中,这个标识就是对象的内存地址,可以通过内置函数id来获取。只要对象还活着,它的id就不会改变;如果两个对象的id相同,那么它们必然是同一个对象,只是可能通过不同的变量名被引用。

我们可以用一段简单代码观察身份的变化:

a = [1, 2, 3]
b = a
print(id(a))   # 输出类似 140245982345728
print(id(b))   # 与上面完全相同
print(a is b)  # True,因为指向同一个列表对象

上面代码中,b = a并没有创建新列表,只是让b引用了a所引用的同一个对象,因此二者身份一致。如果改用b = a.copy(),则会生成一个新对象,即便值相同,身份也不同。

二、对象值的概念

对象值是对象内部保存的、可供程序使用的数据。对于整数来说,值就是那个数字;对于字符串,值就是字符序列;对于列表,值就是其中包含的元素集合。判断两个对象的值是否相等,应当使用等于号运算符,它会调用对象的__eq__方法完成比较。

以下示例展示了值相等但身份不同的情况:

x = [1, 2, 3]
y = [1, 2, 3]
print(x == y)  # True,值相等
print(x is y)  # False,不是同一个对象
print(id(x))   # 假设 140245982345920
print(id(y))   # 假设 140245982346000,不同

这里x和y内容一模一样,所以等于号返回True;但它们是两次独立构造的列表,解释器分配了不同内存块,身份比较自然为False。日常业务中需要判断“数据是否相同”时,应优先使用等于号而非is。

三、is与等于号的选择

is用于比较对象身份,等于号用于比较对象值,这是Python最基本的规则。误用is去比较值,会在某些情况下“碰巧正确”,从而埋下隐患。例如小整数和短字符串会被解释器缓存复用,导致不同变量拿到同一身份。

看一个容易踩坑的例子:

m = 256
n = 256
print(m is n)   # 多数情况下 True,因小整数缓存

p = 257
q = 257
print(p is q)   # 可能为 False,超出缓存范围
print(p == q)   # True,值始终相等

由于Python默认缓存范围在负五到二百五十六的小整数,m和n指向同一个缓存对象,is成立;而257通常不在缓存内,p和q是独立对象。如果代码依赖is判断数值,当数值变大就会出错。因此,比较数据内容务必用等于号,只在明确需要判断“是否为同一对象”时才用is,比如判断变量是否为None。

四、函数传参时的身份与值

Python采用“传对象引用”的方式,函数参数传递的是对象的引用,而非副本。如果传入可变对象,函数内通过引用修改原对象,会影响外部变量,因为这二者身份相同。理解这一点,就能解释为何列表会在函数里被改动。

示例说明如下:

def append_item(lst):
    lst.append(99)
    print(id(lst))

data = [1, 2]
print(id(data))
append_item(data)
print(data)   # [1, 2, 99],原列表被修改

调用时data和lst身份一致,函数内追加元素直接作用于原列表。如果想避免修改,应传入副本:append_item(data.copy())。相反,不可变对象如整数、字符串,函数内重新赋值只是让局部变量引用新对象,不影响外部,因为其值无法原地修改。

五、总结对照表

为便于记忆,可以把核心区别整理成表格:

比较维度对象身份对象值
含义内存中的唯一标识对象承载的数据内容
获取方式id(obj)obj本身或print(obj)
比较运算符is / is not== / !=
相同条件同一块内存对象逻辑内容相等

掌握对象身份与对象值的分界,不仅能正确使用比较符,也能理清变量引用、参数传递与缓存机制之间的关系,让Python代码更加稳健可预测。

Python对象身份对象值修改时间:2026-08-09 16:15:39

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