python - super() 类继承,钻石问题
问题描述
为什么当我调用super()
类WordCounter
时它调用类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 也不例外。(请注意,我在解释 Python 中的“新样式”类。Python 2 中也有“经典”类,它们的行为不同)
Python 对所有继承所做的事情是,如果当前类未实现请求的方法/属性,则呈现检查父类的顺序。您可以动态检查此方法解析顺序。你的例子产生
>>> print(TextDescriber.__mro__)
(<class '__main__.TextDescriber'>, <class '__main__.WordCounter'>, <class '__main__.Vocabulary'>, <class '__main__.Tokenizer'>, <class 'object'>)
如您所见,Python 选择从左到右,然后才在层次结构中下降(完整细节)。
什么super()
是调用 this 中的下一个方法__mro__
。该链在 处停止Vocabulary.__init__()
,因为该方法不需要super().__init__()
链继续。
如果您在 中包含一个super().__init__()
调用Vocabulary.__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__()
推荐阅读
- javascript - 数组不同时如何更改类别?
- python - 嵌套字典迭代
- java - JAVA中没有双引号的ExpressionParser
- excel - FormulaArray 突击队不适用于 VBA 执行代码
- php - PHP如何循环嵌套的JSON对象?
- python - 绘制虚拟变量 == 1 和系列中的单独变量 == 1 的计数条形图
- flutter - 如何更改颤振 filterChip 中的复选图标颜色
- sql - 将复制值从 A 列插入到 B 列后创建触发器
- c++ - 向 OpenCL 项目函数添加参数时出现链接器问题
- c# - RestSharp - .AddParameter 是否添加到 POST 请求的 Header 或 Body 中?