什么是Python中的对象身份?
Python中的每个对象都有一个唯一的身份。身份告诉Python对象在内存中的位置。只要对象存在,这个身份就是固定的,不会改变。
您可以使用 id()
函数检查对象的身份。您还可以使用 is
运算符比较两个对象的身份。如果两个名称指向同一个对象,它们的身份就是相同的。
Python允许您使用 is
和 id()
比较对象身份。
a = [1, 2, 3]
b = a
print(a is b) # True
print(id(a), id(b)) # Same number
身份与值有什么不同?
对象的值是它所包含的内容。身份是它所处的位置。两个对象可以具有相同的值,但身份不同。这种情况在可变对象(如列表)中经常发生。
身份在你想知道两个名称是否指向完全相同的对象时非常有用。它并不能告诉你它们的内容是否相等。这就是 ==
运算符的作用。
对象身份来自哪里?
对象身份的概念源于早期计算机,在那里内存中的每个项目都有一个地址。Python 保留了这一概念,以帮助管理内存和对象行为。
人们建立了基于内存的系统。
1945年 — 具有地址身份的内存模型,冯·诺依曼架构为每个值提供了一个固定的位置。
1972年 — C语言中的指针,使对象身份变得可见并有助于跟踪内存。
1983年 — 引用计数,在CPython中使用,用于跟踪有多少名称指向一个对象。
人们将身份作为Python的一部分。
1991 — Python 0.9.0,每个对象都有一个唯一的身份,可以通过 is
进行比较。
2000 — id()
函数稳定,Python 2.0 使得 id()
始终返回一个反映对象身份的数字。
2025 — 身份规则不变,Python 仍然在底层使用内存地址身份。
对象身份如何帮助你了解事物的本质?
Python 使用身份来帮助追踪名称所指代的内容。当测试共享状态、缓存或理解变更时,身份是非常有用的。这些示例展示了对象身份如何帮助解决常见任务。
问题 1:测试两个名称是否指向同一个对象
问题:你把一本书递给你的朋友。后来,你的朋友把书还给你。你想知道这是否是同一本书。
解决方案:使用 is
运算符来检查身份。使用 ==
来检查值。
Python 让你可以测试两个名称是否指向同一个对象。
book1 = ["title", "author"]
book2 = book1
print(book1 is book2) # True
这两个名称都指向内存中的同一个对象。
问题 2:相同的值,不同的对象
问题:你有两个看起来相同的塑料杯,但它们并不是同一个副本。
解决方案:两个对象可能看起来相同,但位于不同的位置。使用 is
来测试身份。
Python 允许你区分相同值和相同对象的情况。
cup1 = [1, 2]
cup2 = [1, 2]
print(cup1 == cup2) # True
print(cup1 is cup2) # False
这两个列表对象是不同的,尽管它们看起来相同。
问题 3:跟踪共享变更
问题:你发放了两份表单的副本。你更改了一份,另一份也随之更改。你意识到它们是同一份副本。
解决方案:当两个名称共享身份时,一个的变化会影响另一个。
Python 允许你通过身份追踪共享状态。
form1 = {"name": "Ada"}
form2 = form1
form2["name"] = "Alan"
print(form1["name"]) # "Alan"
这两个名称指向同一个字典,因此其中一个的变化在两个名称中都会体现。
问题 4:不可变类型中的身份重用
问题:你在两行中分别赋值 a = 1
和 b = 1
。你想知道它们是否是同一个对象。
解决方案:对于像整数这样的较小不可变类型,Python 可能会重用相同的对象。
Python 可能会重用具有相同值的不可变对象。
a = 1
b = 1
print(a is b) # 通常为 True
Python 可能会给两个名称相同的身份,但这并不保证对所有值都适用。
问题 5:避免意外共享状态
问题:你想要复制一个列表,但两个名称指向同一个列表。当你改变一个时,另一个也会改变。
解决方案:使用 copy()
或切片来创建一个具有新身份的新对象。
Python 通过复制让你避免共享身份。
a = [1, 2, 3]
b = a.copy()
a[0] = 99
print(b[0]) # 仍然是 1
现在 a
和 b
指向不同的对象,但它们的初始值相同。
你觉得这有帮助吗?请通过点击下面的点赞按钮告诉我。我也很想听听你在评论中的想法!如果你想看到更多类似的内容,不要忘记订阅我的频道。感谢你的阅读!