派生类时python abc subclasshook没有效果

Posted

技术标签:

【中文标题】派生类时python abc subclasshook没有效果【英文标题】:python abc subclasshook has no effect when class is derived 【发布时间】:2017-07-22 13:45:43 【问题描述】:

当类派生自具有__sub***ook__ 实现的类时,无法从issubclass 返回False。我修改了以下代码: python subclasscheck & subclasshook 我只在两个类定义中添加了 '(Sized)':

from abc import ABCMeta

class Sized(metaclass=ABCMeta):
    @classmethod
    def __subclasshook__(cls, C):
        if cls is Sized:
            if any("__len__" in B.__dict__ for B in C.__mro__):
                return True
        return NotImplemented

class A(Sized):
    pass

class B(Sized):
    def __len__(self):
        return 0

print(issubclass(A, Sized))  # True - should be False
print(issubclass(B, Sized))  # True

在这种情况下有没有办法返回False?还是我做错了什么?

【问题讨论】:

当然我发现代码片段(在 abc 中)以:ok = cls.__subclasshook__(subclass) 如果我遗漏了一些东西,请原谅,但你能不能用return False 替换return NotImplemented 吗?您在 PEP8 中有什么要坚持的吗? @leaf:谢谢,太明显了。但是为什么所有的例子都只返回TrueNotImplemented 我相信这是因为 [Python]() 标准在实现“魔术方法”时所要求的。 【参考方案1】:

问题是你return NotImplemented__subclasshook__ 没有提前退出。正如documentation中所述:

如果它返回 NotImplemented,则使用通常的机制继续检查子类。

所以它使用普通的子类检查并发现你确实继承自Sized所以返回True

有两种解决方案:

    return False 而不是return NotImplemented。但是,您真的希望/需要issubclass直接子类返回False

    如果您从 object 继承 AB 类,它将按预期工作:

    class A(object):
        pass
    
    class B(object):
        def __len__(self):
            return 0
    
    print(issubclass(A, Sized))  # False
    print(issubclass(B, Sized))  # True
    

【讨论】:

Ad 1. 是的,假设这是类似于其他语言中的编译(或反射)的机制。如果怀疑该类是正确的子类,则代码不应运行甚至编译(不在 python 中)。广告 2. 我明白了,是来自链接的代码。【参考方案2】:

我认为实现这一点的好方法:

from abc import ABCMeta

class Sized(metaclass=ABCMeta):
    @classmethod
    def __subclasshook__(cls, C):
        if cls is Sized:
            if any("__len__" in B.__dict__ for B in C.__mro__):
                return True
            else:
                return False
        return NotImplemented


class A(Sized):
    pass


class B(Sized):
    def __len__(self):
        return 0


print(issubclass(A, Sized))  # False
print(issubclass(B, Sized))  # True

我认为当我们假设abc 是类似于其他语言中的编译(或反射)的机制时,我们应该返回 False。如果怀疑该类是正确的子类,则代码不应运行甚至编译(不在 python 中)。

【讨论】:

请不要只是转储代码,请解释为什么这样可以解决问题。否则您可能还想考虑accept我的回答,其中还包含相关信息+解释。

以上是关于派生类时python abc subclasshook没有效果的主要内容,如果未能解决你的问题,请参考以下文章

定义派生类时,为啥基类标记为“public”? [复制]

当有多个派生类时,如何使用基类指针访问派生类的函数成员?

使用派生 Qt 小部件类时的父问题 (?)

在不同的命名空间中定义基类和派生类时的编译错误

使用Boost将派生类部分反序列化为基类时输入流错误

在 C++ 继承中,当指向基类的指针对象指向派生类时,不调用派生类析构函数