python - super()类继承,菱形继承(钻石问题)

标签 python inheritance superclass

为什么当我在 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/

相关文章:

python - PyODE 是否支持复合对象?

java - Java 中的继承、泛型和转换

c++ - 我对 c++ 纯虚函数和接口(interface)的误解

java - Java中如何从父类(super class)调用子类方法?

python - 获取从模块中的特定类派生的类

python - 如何在selenium上抓取产品详细信息页面

python - 带有新 key python的boto3 put_object

python - math.sin 不正确的结果

c# - 强制继承者从其 CTOR (C#) 初始化基的字段

java - 将访问器和修改器方法从一个类移至其父类(super class)