Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python a==b为假,但id(a)==id(b)为真?_Python_Object_Methods_Overriding - Fatal编程技术网

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

Python a==b为假,但id(a)==id(b)为真?,python,object,methods,overriding,Python,Object,Methods,Overriding,遇到以下情况: >>> 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()

遇到以下情况:

>>> 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?!
这里发生了什么事?

以下工作:

>>> id(A.__str__.im_func) == id(A.__str__.im_func)
True
>>> id(B.__str__.im_func) == id(A.__str__.im_func)
False
当字符串
id(A.\uu str\uuuuuuu)==id(B.\uu str\uuuuuuuuu)
被计算时,
A.\uu str\uuuuuuu
被创建,其id被获取,然后被垃圾收集。然后创建
B.。\uuuu str\uuuuu
,并且恰好在
A.\uuu str\uuuuu
之前的地址处结束,因此它(在CPython中)获得相同的id

尝试将
A.\uuuu str\uuu
B.\uu str\uuu
分配给临时变量,您将看到不同的结果:

>>> f = A.__str__
>>> g = B.__str__
>>> id(f) == id(g)
False
有关此现象的更简单示例,请尝试:

>>> id(float('3.0')) == id(float('4.0'))
True

对于我们这些被您的标题吸引的人来说,要确定某个方法是否被覆盖:

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

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

但是,为什么>>>f=A.uu str_u>>>id(f)==id(A.uu str_uuu)False@jldupont:Python在运行时创建未绑定的方法
A.\uu str\uu
B.\uu str\uu
。对于底层机制是一个很好的参考。。。那些垃圾能这么快收集起来吗?我仍然不相信这个解释。@jldupont,CPython被重新计数,所以大多数东西都会立即被垃圾收集。这是对发生的事情的正确解释。@jldupont:这个理论很容易验证!尝试创建float的子类
myfloat
,并覆盖
\uuuuu new\uuuuu
\uu del\uuuuu
,以便它们适当地记录调用。现在,观察计算
id(myfloat(1.0))==id(myfloat(2.0))
时的操作顺序。(并不是说对
\uu del\uuu
的调用必然直接对应于垃圾收集。)实际上,不是。这总是正确的,因为方法上的实例永远不等于类上的方法。