起因經過
今天翻collections.abc的文檔時,我知道list的實例在邏輯上(因為duck typing 鴨子類型)是Container和不能hash的(因為list可變),就試下面的代碼是否能行:
from collections.abc import Container, Hashable
print(isinstance(list(), Container)) # return true
print(isinstance(list(), Hashable)) # return False
我就產生疑惑,問題1來了:list是繼承於object, 而collections.abc.Container是個抽象類,isinstance為什么能正確運行?換另外一句話說,此時我的理解是根據isintance的語義來的,list並沒有繼承這個抽象類,why isintance() works?
class list(object):
...
class Container(metaclass=ABCMeta):
...
解決
查找isinstance()文檔:
Return true if the object argument is an instance of the classinfo argument, or of a (direct, indirect or virtual) subclass thereof.
問題2來了,什么是virutal subclass? 剛好virutal那里有個超鏈接,點進去
Abstract base classes complement duck-typing by providing a way to define interfaces .... ABCs introduce virtual subclasses, which are classes that don’t inherit from a class but are still recognized by isinstance() and issubclass();
總結
豁然開朗,想起了以前讀的Fluent Python,因為Python沒有interface,抽象類實現了接口,補充了鴨子類型,加上isinstance支持判斷抽象類,所以就可以判斷。
isinstance支持direct(直接繼承), indirect(非直接繼承), virtual(抽象類)。以前對於isinstance的理解只局限在前兩種。