为什么当我在 WordCounter
类中调用 super()
时,它会调用类 Vocabulary
,即使它不是继承自?它不应该改为调用类 Tokenizer
吗?
class Tokenizer:
"""Tokenize text"""
def __init__(self, text):
print('Start Tokenizer.__init__()')
print('End Tokenizer.__init__()')
class Vocabulary(Tokenizer):
"""Find unique words in text"""
def __init__(self, text):
print('Start init Vocabulary.__init__()')
print('End init Vocabulary.__init__()')
class WordCounter(Tokenizer):
"""Count words in text"""
def __init__(self, text):
print('Start WordCounter.__init__()')
super().__init__(text)
print('End WordCounter.__init__()')
class TextDescriber(WordCounter, Vocabulary):
"""Describe text with multiple metrics"""
def __init__(self, text):
print('Start init TextDescriber.__init__()')
super().__init__(text)
print('End init TextDescriber.__init__()')
td = TextDescriber('row row row your boat')
输出:
Start init TextDescriber.__init__()
Start WordCounter.__init__()
Start init Vocabulary.__init__()
End init Vocabulary.__init__()
End WordCounter.__init__()
End init TextDescriber.__init__()
最佳答案
菱形继承(钻石问题)总是有点乱。每种语言都有自己的怪癖,Python 也不异常(exception)。 (请注意,我在解释 Python 中的“新式”类。Python 2 中也有“经典”类,它们的行为有所不同)
Python 对所有继承所做的是,如果当前类未实现请求的方法/属性,则呈现一个检查父类的顺序。您可以动态检查此方法解析顺序。你的例子产生了
>>> print(TextDescriber.__mro__)
(<class '__main__.TextDescriber'>, <class '__main__.WordCounter'>, <class '__main__.Vocabulary'>, <class '__main__.Tokenizer'>, <class 'object'>)
如您所见,Python 选择从左到右,然后才在层次结构中降级 ( full details )。
super()
所做的是调用此 __mro__
中的下一个方法。此链在 Vocabulary.__init__()
处停止,因为此方法没有 super().__init__()
调用以继续链。
如果您在 Vocabulary.__init__()
中包含一个 super().__init__()
调用,这将按预期工作:
Start init TextDescriber.__init__()
Start WordCounter.__init__()
Start init Vocabulary.__init__()
Start Tokenizer.__init__()
End Tokenizer.__init__()
End init Vocabulary.__init__()
End WordCounter.__init__()
End init TextDescriber.__init__()
关于python - super()类继承,菱形继承(钻石问题),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62359677/