为什么 CPython 中 id({}) == id({}) 和 id([]) == id([]) ?

发布于 2024-09-26 02:16:18 字数 748 浏览 5 评论 0原文

为什么 CPython(不知道其他 Python 实现)有以下行为?

tuple1 = ()
tuple2 = ()                                                                                                   
dict1 = {}
dict2 = {}
list1 = []
list2 = []
# makes sense, tuples are immutable
assert(id(tuple1) == id(tuple2))
# also makes sense dicts are mutable
assert(id(dict1) != id(dict2))
# lists are mutable too
assert(id(list1) != id(list2))
assert(id(()) == id(()))
# why no assertion error on this?
assert(id({}) == id({}))
# or this?
assert(id([]) == id([]))

我有一些想法可能,但找不到具体原因。

编辑

为了进一步证明格伦和托马斯的观点:

[1] id([])
4330909912
[2] x = []
[3] id(x)
4330909912
[4] id([])
4334243440

Why does CPython (no clue about other Python implementations) have the following behavior?

tuple1 = ()
tuple2 = ()                                                                                                   
dict1 = {}
dict2 = {}
list1 = []
list2 = []
# makes sense, tuples are immutable
assert(id(tuple1) == id(tuple2))
# also makes sense dicts are mutable
assert(id(dict1) != id(dict2))
# lists are mutable too
assert(id(list1) != id(list2))
assert(id(()) == id(()))
# why no assertion error on this?
assert(id({}) == id({}))
# or this?
assert(id([]) == id([]))

I have a few ideas why it may, but can't find a concrete reason why.

EDIT

To further prove Glenn's and Thomas' point:

[1] id([])
4330909912
[2] x = []
[3] id(x)
4330909912
[4] id([])
4334243440

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

GRAY°灰色天空 2024-10-03 02:16:18

当您调用 id({}) 时,Python 会创建一个字典并将其传递给 id 函数。 id 函数获取其 id(其内存位置),并丢弃该字典。该字典已被销毁。当你快速连续执行两次(同时没有创建任何其他字典)时,Python 第二次创建的字典恰好使用与第一次相同的内存块。 (CPython 的内存分配器使这种情况比听起来更有可能发生。)由于(在 CPython 中)id 使用内存位置作为对象 id,因此两个对象的 id 是相同的。如果您将字典分配给变量然后获取其 id() ,显然不会发生这种情况,因为字典同时处于活动状态,因此它们的>id 必须不同。

可变性并不直接发挥作用,但缓存元组和字符串的代码对象会直接发挥作用。在相同的代码对象(函数或类体或模块体)中,相同的文字(整数、字符串和某些元组)将被重复使用。可变对象永远不能重用,它们总是在运行时创建。

简而言之,对象的 id 仅在该对象的生命周期内是唯一的。在对象被销毁之后,或者在创建之前,其他对象可以具有相同的 id。

When you call id({}), Python creates a dict and passes it to the id function. The id function takes its id (its memory location), and throws away the dict. The dict is destroyed. When you do it twice in quick succession (without any other dicts being created in the mean time), the dict Python creates the second time happens to use the same block of memory as the first time. (CPython's memory allocator makes that a lot more likely than it sounds.) Since (in CPython) id uses the memory location as the object id, the id of the two objects is the same. This obviously doesn't happen if you assign the dict to a variable and then get its id(), because the dicts are alive at the same time, so their id has to be different.

Mutability does not directly come into play, but code objects caching tuples and strings do. In the same code object (function or class body or module body) the same literals (integers, strings and certain tuples) will be re-used. Mutable objects can never be re-used, they're always created at runtime.

In short, an object's id is only unique for the lifetime of the object. After the object is destroyed, or before it is created, something else can have the same id.

柏林苍穹下 2024-10-03 02:16:18

CPython 会在对象超出范围时立即对其进行垃圾收集,因此第二个 [] 是在第一个 [] 被收集后创建的。因此,大多数时候它最终会出现在同一个内存位置。

这非常清楚地显示了发生的情况(输出在 Python 的其他实现中可能有所不同):

class A:
    def __init__(self): print("a")
    def __del__(self): print("b")

# a a b b False
print(A() is A())
# a b a b True
print(id(A()) == id(A()))

CPython is garbage collecting objects as soon as they go out of scope, so the second [] is created after the first [] is collected. So, most of the time it ends up in the same memory location.

This shows what's happening very clearly (the output is likely to be different in other implementations of Python):

class A:
    def __init__(self): print("a")
    def __del__(self): print("b")

# a a b b False
print(A() is A())
# a b a b True
print(id(A()) == id(A()))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文