多态性和来自模块的调用

Polymorphism and calls from a module

我在 python 的面向对象编程中使用多态性时遇到问题。在这里,我定义了列表 class 的特化,它覆盖了 append 和 setitem 方法

class MyList(list):
    def __setitem__(self, key,value):
        super(MyList,self).__setitem__(key,value)
        print("bubu")
    def append(self,value):
        super(MyList,self).append(value)
        print("bibi")

现在如果我用

测试这个class
myobj = MyList()
myobj.append(1) 
myobj[0]=3

如预期的那样,我得到了“bibi”,然后是“bubu”。但是如果我将 MyList 对象与外部模块一起使用

import heapq
myobj = MyList()
heapq.heappush(myobj,1) 

heapq 中的函数 heappush 应该调用 myobj.append(我检查了来源 https://github.com/python/cpython/blob/3.10/Lib/heapq.py)。但是这次我没有得到“比比”!调用的“追加”不应该是参数中传递的实例的追加吗?

我的比比斯呢?? :)

如果您 运行 Python 不带任何参数并输入以下内容,我可以肯定您不会遇到导入错误:

>>>
>>>
>>> from _heapq import *
>>>

我提到这个是因为如果你更深入地查看 heapq 的源代码,你会在底部看到:

# If available, use C implementation
try:
    from _heapq import *
except ImportError:
    pass
... # etc.

并且由于我们没有理由相信您的 MyList 方法 append 的实现没有正常工作,仅凭这一点就应该表明 heapq.heappush 方法是 not 调用列表中的 append 方法。现在我们不知道为什么。

更新

加载 heapq 不带 _heapq:

import sys
import importlib
import _heapq

 # Make _heapq unloadable
del _heapq
sys.modules['_heapq'] = None

# heapq was already loaded with _heapq; get a reference:
heapq = sys.modules['heapq']
# reload heapq, but this time without _heapq:
importlib.reload(heapq)

class MyList(list):
    def __setitem__(self, key,value):
        super(MyList,self).__setitem__(key,value)
        print("bubu")
    def append(self,value):
        super(MyList,self).append(value)
        print("bibi")

myobj = MyList()
heapq.heappush(myobj,1)

打印:

bibi
bubu

'bubu' 和 'bibi' 打印很有趣。这是 _siftdown 方法的结果,heappush 最终调用了 'bubu'.