微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

实现 __contains__ 方法时从 collections.abc.Container 类隐式继承

如何解决实现 __contains__ 方法时从 collections.abc.Container 类隐式继承

所以,我对 Python 有点陌生,对 OOP 范式也有点陌生,最近我遇到了一些似乎有点违反直觉的事情。例如,看看下面的代码(在 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,说明OddContainerContainer的子类,但是OddContainer类没有明确指定其超类。 有人能告诉我这里到底发生了什么吗?说任何具有内部重载 __contains__() 方法的类都成为 Container 类的子类是否正确,还是一种幼稚的解释?如果前者是正确的,那么还有没有其他通过方法重载发生这种继承的情况?

提前致谢。

解决方法

TL;DR isinstance 并非纯粹基于继承。被测试的类可以为自己定义作为类的实例意味着什么。 (不要将“x 是 C 的一个实例”与“x 的类型继承自 C”混淆。)


Container 定义 __subclasshook__ 使任何具有 __contains__ 方法的类都被视为子类,无论 Container 是否是通过继承的类的实际祖先。

以下是 Python 3.9 中 collections.abc.Container](https://github.com/python/cpython/blob/3.9/Lib/_collections_abc.py#L388) 的完整定义:

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__ 优先于继承检查。

在确定某个类 C 是否是 Container 的子类时,会调用 Container.__subclasshook__(C)。如果 C.__contains__ 存在,则返回 True;如果不是,则返回 False。 (我不确定是否值得深入研究如何调用 Container.__subclasshook__cls notContainer。)

,

来自docs of isinstance

如果对象参数是 classinfo 参数或其(直接、间接或虚拟)子类的实例,则返回 True。

强调我的。当点击“虚拟”链接时,会导致词汇表中“ABC”的描述指出:

ABC 引入了虚子类,它们是不从类继承但仍被 isinstance() 和 issubclass() 识别的类;请参阅 abc 模块文档。

因此,OddContainer 被认为是一个“虚拟子类”,因为它满足了 Container ABC。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。