【发布时间】:2021-06-25 05:00:05
【问题描述】:
我想弄清楚在 Python 中处理多重继承时,为什么不将具体子类视为抽象子类的子类。
参见下面的代码 sn-p。
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 继承自ConcreteFirstParent 和ConcreteSecondParent,那么它继承自AbstractFirstParent 和AbstractSecondParent。
因此,它必须继承自 AbstractChild,但由于某种原因它没有。
例如,
print(
issubclass(ConcreteChild, AbstractFirstParent)
and issubclass(ConcreteChild, AbstractSecondParent)
)
给出True,这是预期的。
谁能解释为什么ConcreteChild 不被视为AbstractChild 的子类?
提前谢谢你!
这是层次结构的可视化表示。
AFP ASP
| \ / |
| \ / |
| \ / |
| AC |
CFP CSP
\ /
\ /
\ /
\ /
CC
我问的原因涉及系统类型检查的实现,其中各种 mixin 类用于组成一个具体的类。
在我看来,如果ConcreteChild 继承自两个抽象父级,就像AbstractChild,那么它应该继承自后者。
现在我看到 CC 和 AC 之间没有直接联系,这就是为什么 ConcreteChild 不被视为 AbstractChild 的子类的原因。
但目前尚不清楚在这种情况下如何处理类型检查。
比方说,一个函数返回一个ConcreteChild 实例,而基于各种具体的父级可能有各种ConcreteChild。
所有的父母都是基于AbstractFirstParent 和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))
根据需要给予。
True
False
【问题讨论】:
-
AbstractChild是它自己的类,而不是交集类型或“AbstractFirstParent 和 AbstractSecondParent”。作为 AbstractFirstParent 和 AbstractSecondParent 的子类不会使类成为 AbstractChild 的子类。
标签: python multiple-inheritance subclassing