打开网易新闻 查看精彩图片
写Python的人迟早会撞上继承。类写多了,重复代码像野草一样疯长——同样的属性在三个文件里各写一遍,改个字段要全局搜索替换。
Python的解法看起来优雅:子类继承父类,代码复用,完事。但官方文档没告诉你的是,super()在多重继承里的调用顺序,跟俄罗斯轮盘赌差不多。
MRO(方法解析顺序)算法从Python 2.3就定死了,C3线性化。听起来像编译器黑魔法,其实就一条规则:子类永远在父类前面,多个父类按声明顺序排。但真到调试时,你会发现某个父类的方法被"跳过"了——不是bug,是你的继承链画成了菱形。
「钻石继承问题不是Python的缺陷,是设计选择。」Guido van Rossum在2009年的邮件列表里写过这句话。他选了C3,放弃了深度优先,代价就是开发者得自己理清楚MRO链条。
现在回头看,那些早期教程用动物-狗-哈士奇的例子讲继承,跟用"hello world"教并发一样无害。真到生产环境,Django的ORM、Scrapy的Spider、甚至unittest.TestCase,全在多重继承上叠罗汉。一个super().__init__()没接好,初始化顺序错一位,调试能吃掉你整个下午。
2024年Stack Overflow的调研显示,67%的Python开发者自认"熟悉OOP",但只有29%能正确画出自己项目的继承关系图。剩下的,大概都在用print(self.__class__.__mro__)临时抱佛脚。
热门跟贴