a == b 是假的,但 id(a) == id(b) 是真的?
Posted
技术标签:
【中文标题】a == b 是假的,但 id(a) == id(b) 是真的?【英文标题】:a == b is false, but id(a) == id(b) is true? 【发布时间】:2011-01-20 02:50:54 【问题描述】:遇到以下情况:
>>> class A:
... def __str__(self):
... return "some A()"
...
>>> class B(A):
... def __str__(self):
... return "some B()"
...
>>> print A()
some A()
>>> print B()
some B()
>>> A.__str__ == B.__str__
False # seems reasonable, since each method is an object
>>> id(A.__str__)==id(B.__str__)
True # what?!
这是怎么回事?
【问题讨论】:
【参考方案1】:以下作品:
>>> id(A.__str__.im_func) == id(A.__str__.im_func)
True
>>> id(B.__str__.im_func) == id(A.__str__.im_func)
False
【讨论】:
【参考方案2】:在评估字符串id(A.__str__) == id(B.__str__)
时,会创建A.__str__
,获取其ID,然后进行垃圾收集。然后B.__str__
被创建,并且恰好到达与A.__str__
之前完全相同的地址,因此它(在CPython 中)获得了相同的ID。
尝试将A.__str__
和B.__str__
分配给临时变量,你会看到不同的东西:
>>> f = A.__str__
>>> g = B.__str__
>>> id(f) == id(g)
False
对于这种现象的一个更简单的例子,试试:
>>> id(float('3.0')) == id(float('4.0'))
True
【讨论】:
但是,为什么 >>> f = A.__str__ >>> id(f) == id(A.__str__) False @jldupont:Python 在运行时创建未绑定的方法A.__str__
和B.__str__
。 users.rcn.com/python/download/Descriptor.htm 是一个很好的底层机制参考。
hmmm...那些垃圾能这么快被收集起来吗?我仍然不相信这种解释。
@jldupont,CPython 被引用,所以大多数东西都会立即被垃圾收集。这是对所发生情况的正确解释。
@jldupont:测试理论很容易!尝试创建 float 的子类 myfloat
,并覆盖 __new__
和 __del__
,以便它们正确记录调用。现在观察评估id(myfloat(1.0)) == id(myfloat(2.0))
时的操作顺序。 (不过,对__del__
的调用不一定直接对应于垃圾回收。)【参考方案3】:
对于我们这些被你的标题所吸引的人,确定一个方法是否被覆盖:
class A:
def __str__(self):
return "some A()"
def strWasOverridden(self):
return A.__str__ != self.__str__
【讨论】:
其实,没有。这总是正确的,因为方法上的实例永远不会等于类上的方法。以上是关于a == b 是假的,但 id(a) == id(b) 是真的?的主要内容,如果未能解决你的问题,请参考以下文章
Python:将空字符串与False进行比较是假的,为什么?
为啥文档不存在。但所有时间 !snapshot.hasData 都是假的
八枚硬币 有一个是假的 用一个天平秤两次找出那个假的 怎么做