Issubclass 和多重继承

问题描述

我想弄清楚在 Python 中处理多重继承时,为什么不将具体子类视为抽象子类的子类。

请参阅下面的代码片段。


from abc import ABC


class AbstractFirstParent(ABC):
    pass


class AbstractSecondParent(ABC):
    pass


class AbstractChild(AbstractFirstParent,AbstractSecondParent):
    pass


class ConcreteFirstParent(AbstractFirstParent):
    pass


class ConcreteSecondParent(AbstractSecondParent):
    pass


class ConcreteChild(ConcreteFirstParent,ConcreteSecondParent):
    pass


print(issubclass(ConcreteChild,AbstractChild))

输出False,但是我希望如果 ConcreteChild 继承自 ConcreteFirstParentConcreteSecondParent,那么它继承自 AbstractFirstParent 和 {{1 }}。 因此,它必须从 AbstractSecondParent 继承,但由于某种原因它没有。

例如

AbstractChild

给出 print( issubclass(ConcreteChild,AbstractFirstParent) and issubclass(ConcreteChild,AbstractSecondParent) ) ,这是预期的。

谁能解释为什么 True 不被视为 ConcreteChild 的子类?

先谢谢你!

这是层次结构的直观表示。

AbstractChild

我问的原因与系统类型检查的实现有关,其中各种混合类用于组成一个具体的类。

在我看来,如果 AFP ASP | \ / | | \ / | | \ / | | AC | CFP CSP \ / \ / \ / \ / CC 继承自两个抽象父对象,就像 ConcreteChild 一样,那么它应该继承自后者。

现在我看到 CC 和 AC 之间没有直接联系,这就是为什么 AbstractChild 不被视为 ConcreteChild 的子类的原因。 但不清楚在这种情况下如何处理类型检查。 让我们说,一个函数返回一个 AbstractChild 实例,而根据不同的具体父级可能有各种类型的 ConcreteChild。 所有的父项都基于 ConcreteChildAbstractFirstParent。 我希望函数返回值的类型是 AbstractSecondParent,因为它继承自两个抽象父项。

我们能否以某种方式篡改 AbstractChild 以使其有效?

回答

这种方法,使用虚拟继承会有所帮助。

__subclasscheck__

在这种情况下,它按预期工作。

class ChildMeta(type):
    def __subclasscheck__(cls,sub):
        return (
            issubclass(sub,AbstractFirstParent)
            and issubclass(sub,AbstractSecondParent)
        )


class AbstractChild(Metaclass=ChildMeta):
    pass

根据需要给予。

print(issubclass(ConcreteChild,AbstractChild))
print(issubclass(ConcreteFirstParent,ConcreteChild))

解决方法

ConcreteFirstParentConcreteSecondParentAbstractChild 在当前代码中就像兄弟一样。 ConcreteChildConcreteFirstParentConcreteSecondParent 继承,即它不从 AbstractChild 继承任何东西。所以 ConcreteChild 确实不是 AbstractChild 的子类。

(不完全准确)家谱草图:

   AFP   ASP
   /   |   \
CFP   CSP   AC
    |
   CC