a == b 为假,但 id(a) == id(b) 为真?

13 投票
3 回答
1488 浏览
提问于 2025-04-15 19:38

遇到以下情况:

>>> 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?!

这是怎么回事呢?

3 个回答

0

对于我们这些被你标题吸引的人来说,要判断一个方法是否被重写,可以这样做:

class A:
    def __str__(self):
        return "some A()"

    def strWasOverridden(self):
        return A.__str__ != self.__str__
8

下面的代码可以正常运行:

>>> id(A.__str__.im_func) == id(A.__str__.im_func)
True
>>> id(B.__str__.im_func) == id(A.__str__.im_func)
False
11

当我们计算字符串 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

撰写回答