为什么 Python 类的 id 在快速调用时不是唯一的? [英] Why is the id of a Python class not unique when called quickly?

查看:19
本文介绍了为什么 Python 类的 id 在快速调用时不是唯一的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用 Python (3.3.3) 做一些事情,我遇到了一些让我感到困惑的事情,因为据我所知,每次调用类时都会得到一个新的 id.

假设你在一些 .py 文件中有这个:

class someClass: pass打印(一些类())打印(一些类())

上面返回了相同的 id,这让我很困惑,因为我正在调用它,所以它不应该是相同的,对吧?当同一个类被连续调用两次时,Python 是这样工作的吗?当我等待几秒钟时,它会给出不同的 id,但如果我像上面的例子一样这样做,它似乎不会那样工作,这让我很困惑.

<预><代码>>>>打印(someClass());打印(someClass())<__main__.someClass 对象在 0x0000000002D96F98><__main__.someClass 对象在 0x0000000002D96F98>

它返回同样的东西,但为什么呢?我也注意到它的范围例如

for i in range(10):打印(一些类())

当类被快速调用时,Python 这样做有什么特别的原因吗?我什至不知道 Python 这样做了,或者它可能是一个错误?如果它不是错误,有人可以向我解释如何修复它或方法,以便在每次调用方法/类时生成不同的 id?我对这是如何做到的感到非常困惑,因为如果我等待,它确实会改变,但如果我尝试调用同一个类两次或更多次,则不会.

解决方案

对象的 id 仅保证在该对象的生命周期内唯一,而不是超过程序的整个生命周期.您创建的两个 someClass 对象仅在调用 print 期间存在 - 之后,它们可用于垃圾收集(并且,在 CPython 中,立即释放).由于它们的生命周期不重叠,因此它们共享一个 id 是有效的.

在这种情况下也不足为奇,因为结合了两个 CPython 实现细节:首先,它通过引用计数进行垃圾收集(使用一些额外的魔法来避免循环引用问题),其次,一个对象的 id 与变量的底层指针的值(即它的内存位置)有关.因此,第一个对象,即最近分配的对象,会立即被释放 - 下一个 分配的对象将在同一位置结束并不奇怪(尽管这可能也取决于有关如何编译解释器的详细信息).

如果您依赖于多个具有不同 id 的对象,您可以将它们保留在周围 - 例如,在一个列表中 - 以便它们的生命周期重叠.否则,您可能会实现具有不同保证的特定于类的 id - 例如:

class SomeClass:next_id = 0def __init__(self):self.id = SomeClass.nextidSomeClass.nextid += 1

I'm doing some things in Python (3.3.3), and I came across something that is confusing me since to my understanding classes get a new id each time they are called.

Lets say you have this in some .py file:

class someClass: pass

print(someClass())
print(someClass())

The above returns the same id which is confusing me since I'm calling on it so it shouldn't be the same, right? Is this how Python works when the same class is called twice in a row or not? It gives a different id when I wait a few seconds but if I do it at the same like the example above it doesn't seem to work that way, which is confusing me.

>>> print(someClass());print(someClass())
<__main__.someClass object at 0x0000000002D96F98>
<__main__.someClass object at 0x0000000002D96F98>

It returns the same thing, but why? I also notice it with ranges for example

for i in range(10):
    print(someClass())

Is there any particular reason for Python doing this when the class is called quickly? I didn't even know Python did this, or is it possibly a bug? If it is not a bug can someone explain to me how to fix it or a method so it generates a different id each time the method/class is called? I'm pretty puzzled on how that is doing it because if I wait, it does change but not if I try to call the same class two or more times.

解决方案

The id of an object is only guaranteed to be unique during that object's lifetime, not over the entire lifetime of a program. The two someClass objects you create only exist for the duration of the call to print - after that, they are available for garbage collection (and, in CPython, deallocated immediately). Since their lifetimes don't overlap, it is valid for them to share an id.

It is also unsuprising in this case, because of a combination of two CPython implementation details: first, it does garbage collection by reference counting (with some extra magic to avoid problems with circular references), and second, the id of an object is related to the value of the underlying pointer for the variable (ie, its memory location). So, the first object, which was the most recent object allocated, is immediately freed - it isn't too surprising that the next object allocated will end up in the same spot (although this potentially also depends on details of how the interpreter was compiled).

If you are relying on several objects having distinct ids, you might keep them around - say, in a list - so that their lifetimes overlap. Otherwise, you might implement a class-specific id that has different guarantees - eg:

class SomeClass:
    next_id = 0

    def __init__(self):
         self.id = SomeClass.nextid
         SomeClass.nextid += 1

这篇关于为什么 Python 类的 id 在快速调用时不是唯一的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆