为什么id(A()) == id(A())的结果与A() is A()的结果不同?

6
我对下面的Python代码感到非常困惑:
>>> class A(): pass  
...  
>>> id(A()) == id(A())  
True  
>>> id(A())  
19873304  
>>> id(A())  
19873304
>>> A() is A()
False
>>> a = A()
>>> b = A()
>>> id (a) == id (b)
False
>>> a is b
False
>>> id (a)
19873304
>>> id (b)
20333272
>>> def f():
...     print id(A())
...     print id(A())
...
>>> f()
20333312
20333312

我可以清楚地告诉自己Python在创建对象时正在做什么。
有人可以多给我解释一下发生了什么吗?谢谢!


请参见https://dev59.com/pXE85IYBdhLWcg3wLAUV。 - Mike Graham
4个回答

5
当你说
print id(A()) == id(A())

您正在创建一个类型为A的对象,并将其传递给id函数。当函数返回时,对于参数创建的对象没有引用。因此,引用计数变为零,它准备进行垃圾回收。

当您在同一表达式中再次执行id(A())时,您正在尝试创建另一个相同类型的对象。现在,Python可能会尝试重用先前创建对象所使用的相同内存位置(如果已经进行了垃圾回收)。否则,它将在不同的位置创建它。因此,id可能相同也可能不同。

如果您采取的话,

print A() is A()

我们创建了一个类型为A的对象,试图将其与另一个类型为A的对象进行比较。现在第一个对象仍然在此表达式中被引用。因此,它不会被标记为垃圾回收,因此引用始终不同。
建议:在生产代码中永远不要做这样的事情。 引用文档中的话:

由于自动垃圾回收、空闲列表和描述符的动态特性,您可能会注意到某些使用is运算符的看似不寻常的行为,比如涉及实例方法或常量之间的比较。请查阅相关文档以获取更多信息。


5

如果一个对象在另一个对象创建之前被释放,那么两个不同的对象可以位于相同的内存位置。

也就是说——如果你分配了一个对象,取得它的id,然后没有更多引用,那么它可以被释放,这样另一个对象就可以获得相同的id。

相反,如果您保留对第一个对象的引用,任何随后分配的对象都必须具有不同的id。


0

A() 创建一个临时变量,然后清除它

因此下一个 A() 获取相同的 ID(刚刚被垃圾回收),尽管这种行为可能不能保证)... 因此当您打印它们时,它们具有相同的 ID

id(A()) == id(A())

必须创建两个临时变量,每个变量都有不同的id


0

由于 id() 基于对象指针,只有在两个对象都在内存中时才能保证唯一性。在某些情况下,A 的第二个实例可能会重用已经被垃圾回收的第一个实例占用的同一内存空间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接