实现 __contains__ 方法时从 collections.abc.Container class 隐式继承
Implicit inheritance from the collections.abc.Container class when implementing __contains__ method
所以,我对 Python 有点陌生,对 OOP 范式也有点陌生,最近我遇到了一些似乎有点违反直觉的事情。例如,查看下面的代码(运行 on Python 3.9):
from collections.abc import Container
class OddContainer:
def __contains__(self, x):
if not isinstance(x, int) or not x%2:
return False
return True
if __name__ == '__main__':
x = OddContainer()
print(isinstance(x, Container))
这里的print
会输出True
,说明OddContainer
是Container
的subclass,但是OddContainer
class 没有明确指定它的超classes。
有人能告诉我这里到底发生了什么吗?说任何在内部重载 __contains__()
方法的 class 成为 Container
class 的子 class 是否正确,或者这是一个天真的解释?如果前者是正确的,那么还有其他情况会发生这种通过方法重载的继承吗?
提前致谢。
Return True if the object argument is an instance of the classinfo argument, or of a (direct, indirect or virtual) subclass thereof.
强调我的。当跟随“virtual”的link时,它会导致词汇表中对“ABC”的描述指出:
ABCs introduce virtual subclasses, which are classes that don’t inherit from a class but are still recognized by isinstance() and issubclass(); see the abc module documentation.
因此,OddContainer
被认为是“虚拟子类”,因为它满足 Container
ABC。
TL;DR isinstance
并非完全基于继承。被测试的 class 可以为自己定义成为 class 实例的含义。 (不要混淆“x 是 C 的一个实例”和“x 的类型继承自 C”。)
Container
定义 __subclasshook__
使任何具有 __contains__
方法的 class 被视为子 class,无论是否 Container
是 class 通过继承的实际祖先。
这是 collections.abc.Container
](https://github.com/python/cpython/blob/3.9/Lib/_collections_abc.py#L388) 在 Python 3.9 中的完整定义:
class Container(metaclass=ABCMeta):
__slots__ = ()
@abstractmethod
def __contains__(self, x):
return False
@classmethod
def __subclasshook__(cls, C):
if cls is Container:
return _check_methods(C, "__contains__")
return NotImplemented
__class_getitem__ = classmethod(GenericAlias)
__subclasshook__
优先于继承检查。
当判断某些 class C
是否是 Container
的子 class 时,调用 Container.__subclasshook__(C)
。如果C.__contains__
存在,则returnsTrue
;如果不是,则 returns 错误。 (我不确定是否值得深入研究如何调用 Container.__subclasshook__
而 cls
不是 是 Container
。)
所以,我对 Python 有点陌生,对 OOP 范式也有点陌生,最近我遇到了一些似乎有点违反直觉的事情。例如,查看下面的代码(运行 on Python 3.9):
from collections.abc import Container
class OddContainer:
def __contains__(self, x):
if not isinstance(x, int) or not x%2:
return False
return True
if __name__ == '__main__':
x = OddContainer()
print(isinstance(x, Container))
这里的print
会输出True
,说明OddContainer
是Container
的subclass,但是OddContainer
class 没有明确指定它的超classes。
有人能告诉我这里到底发生了什么吗?说任何在内部重载 __contains__()
方法的 class 成为 Container
class 的子 class 是否正确,或者这是一个天真的解释?如果前者是正确的,那么还有其他情况会发生这种通过方法重载的继承吗?
提前致谢。
Return True if the object argument is an instance of the classinfo argument, or of a (direct, indirect or virtual) subclass thereof.
强调我的。当跟随“virtual”的link时,它会导致词汇表中对“ABC”的描述指出:
ABCs introduce virtual subclasses, which are classes that don’t inherit from a class but are still recognized by isinstance() and issubclass(); see the abc module documentation.
因此,OddContainer
被认为是“虚拟子类”,因为它满足 Container
ABC。
TL;DR isinstance
并非完全基于继承。被测试的 class 可以为自己定义成为 class 实例的含义。 (不要混淆“x 是 C 的一个实例”和“x 的类型继承自 C”。)
Container
定义 __subclasshook__
使任何具有 __contains__
方法的 class 被视为子 class,无论是否 Container
是 class 通过继承的实际祖先。
这是 collections.abc.Container
](https://github.com/python/cpython/blob/3.9/Lib/_collections_abc.py#L388) 在 Python 3.9 中的完整定义:
class Container(metaclass=ABCMeta):
__slots__ = ()
@abstractmethod
def __contains__(self, x):
return False
@classmethod
def __subclasshook__(cls, C):
if cls is Container:
return _check_methods(C, "__contains__")
return NotImplemented
__class_getitem__ = classmethod(GenericAlias)
__subclasshook__
优先于继承检查。
当判断某些 class C
是否是 Container
的子 class 时,调用 Container.__subclasshook__(C)
。如果C.__contains__
存在,则returnsTrue
;如果不是,则 returns 错误。 (我不确定是否值得深入研究如何调用 Container.__subclasshook__
而 cls
不是 是 Container
。)