Mar*_*urí 15 python inheritance self super method-resolution-order
在Raymond Hettinger 在PyCon 2015上的演讲" 超级考虑超级发言 "中,他解释了super在多重继承环境中使用Python 的优势.这是雷蒙德在演讲中使用的一个例子:
class DoughFactory(object):
def get_dough(self):
return 'insecticide treated wheat dough'
class Pizza(DoughFactory):
def order_pizza(self, *toppings):
print('Getting dough')
dough = super().get_dough()
print('Making pie with %s' % dough)
for topping in toppings:
print('Adding: %s' % topping)
class OrganicDoughFactory(DoughFactory):
def get_dough(self):
return 'pure untreated wheat dough'
class OrganicPizza(Pizza, OrganicDoughFactory):
pass
if __name__ == '__main__':
OrganicPizza().order_pizza('Sausage', 'Mushroom')
Run Code Online (Sandbox Code Playgroud)
有人在台下问雷蒙德有关使用的差异self.get_dough(),而不是super().get_dough().我对Raymond的简要回答并不是很了解,但我编写了这个例子的两个实现来看看差异.两种情况的输出相同:
Getting dough
Making pie with pure untreated wheat dough
Adding: Sausage
Adding: Mushroom
Run Code Online (Sandbox Code Playgroud)
如果您将班级订单OrganicPizza(Pizza, OrganicDoughFactory)改为OrganicPizza(OrganicDoughFactory, Pizza)使用self.get_dough(),您将获得以下结果:
Making pie with pure untreated wheat dough
但是,如果您使用super().get_dough()这是输出:
Making pie with insecticide treated wheat dough
我理解super()雷蒙德解释的行为.但是self多继承场景中的预期行为是什么?
jon*_*rpe 12
只是为了澄清,有四种情况,基于改变第二行Pizza.order_pizza和定义OrganicPizza:
super(),(Pizza, OrganicDoughFactory) (原创):'Making pie with pure untreated wheat dough'self,(Pizza, OrganicDoughFactory):'Making pie with pure untreated wheat dough'super(),(OrganicDoughFactory, Pizza):'Making pie with insecticide treated wheat dough'self,(OrganicDoughFactory, Pizza):'Making pie with pure untreated wheat dough'案例3.令你感到惊讶的是; 如果我们切换继承的顺序但仍然使用super,我们显然最终会调用原始的DoughFactory.get_dough.
什么super确实是问"这是在MRO(方法解析顺序)下一个?" 那OrganicPizza.mro()看起来像什么?
(Pizza, OrganicDoughFactory): [<class '__main__.OrganicPizza'>, <class '__main__.Pizza'>, <class '__main__.OrganicDoughFactory'>, <class '__main__.DoughFactory'>, <class 'object'>](OrganicDoughFactory, Pizza): [<class '__main__.OrganicPizza'>, <class '__main__.OrganicDoughFactory'>, <class '__main__.Pizza'>, <class '__main__.DoughFactory'>, <class 'object'>]这里的关键问题是:后来发生了 Pizza什么?当我们super从内部调用时Pizza,Python将会找到get_dough*.对于1.和2.它是OrganicDoughFactory,所以我们得到纯净,未经处理的面团,但是对于3.和4.它是原始的,经过杀虫剂处理的DoughFactory.
为什么self不同呢?self永远是实例,所以Python get_dough从MRO的开始就寻找.在这两种情况下,如上所示,OrganicDoughFactory在列表中早于DoughFactory,这就是为什么self版本总是未经处理的面团; self.get_dough总是解决OrganicDoughFactory.get_dough(self).
*我认为这super在Python 2.x 中使用的双参数形式中实际上更清楚,这将是super(Pizza, self).get_dough(); 第一个参数是要跳过的类(即Python在该类之后查看MRO的其余部分).
| 归档时间: |
|
| 查看次数: |
926 次 |
| 最近记录: |