Python self和super在多重继承中 [英] Python self and super in multiple inheritance

查看:115
本文介绍了Python self和super在多重继承中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Raymond Hettinger在PyCon 2015上的演讲超级考虑超级发言他解释了在多继承上下文中使用Python中的 super 的优点。这是Raymond在演讲中使用的一个例子:

  class DoughFactory(object):
def get_dough(自我):
返回'杀虫剂处理的小麦面团'


类比萨饼(DoughFactory):
def order_pizza(self,* toppings):
打印('获得面团')
dough = super()。get_dough()
print('使用%s'%面团制作馅饼)
顶部浇头:
print( '添加:%s'%顶部)


class OrganicDoughFactory(DoughFactory):
def get_dough(self):
返回'纯未经处理的小麦面团'


class OrganicPizza(Pizza,OrganicDoughFactory):
传递


如果__name__ =='__main__':
OrganicPizza() .order_pizza('Sausage','Mushroom')

观众中有人 Raymond关于使用 self.get_dough()而不是 super()。get_dough()的区别。我对Raymond的简要回答并不是很了解,但是我编写了这个例子的两个实现来看看差异。两种情况下的输出相同:

 获得面团
用纯未经处理的小麦面团制作馅饼
添加:香肠
添加:蘑菇

如果您从<$ c $更改班级订单c> OrganicPizza(Pizza,OrganicDoughFactory)到 OrganicPizza(OrganicDoughFactory,Pizza)使用 self.get_dough(),你会得到这样的结果:



用纯未加工的小麦面团做馅饼



但是如果你使用 super()。get_dough()这是输出:



用经杀虫剂处理的小麦面团制作馅饼



我理解 super ()雷蒙德解释的行为。但是多继承场景中 self 的预期行为是什么?

解决方案

只是澄清一下,有四种情况,基于改变 Pizza.order_pizza 中的第二行以及 OrganicPizza :


  1. super()(Pizza, OrganicDoughFactory) (原创)'用纯未加工的小麦面团做馅饼'

  2. self (Pizza,OrganicDoughFactory)'用未经处理的纯麦制作馅饼面团'

  3. super()(OrganicDoughFactory,Pizza)'用经过杀虫剂处理的小麦面团做馅饼'

  4. self (OrganicDoughFactory,Pizza)'用纯未加工的小麦面团做馅饼'

案例3令您感到惊讶;如果我们切换继承顺序但仍然使用 super ,我们显然最终会调用原来的 DoughFactory.get_dough 。 / p>




超级真的是要求这是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'>]



这里的关键问题是: <$ em> 之后的比萨?当我们从 Pizza 里面调用 super 时,Python将会找到 get_dough *。对于1.和2.它是 OrganicDoughFactory ,所以我们得到纯净的,未经处理的面团,但是对于3.和4.它是原始的,经过杀虫剂处理的 DoughFactory






为什么 self 不同,那么? self 总是实例,因此Python从一开始就寻找 get_dough MRO。在这两种情况下,如上所示, OrganicDoughFactory 在列表中的位置早于 DoughFactory ,这就是为什么 self 版本总是得到未经处理的面团; self.get_dough 始终解析为<​​code> OrganicDoughFactory.get_dough(self)






* 我认为这在Python中使用的 super 的双参数形式中更为明显2.x,这将是 super(Pizza,self).get_dough();第一个参数是要跳过的类(即Python在该类之后查看MRO的其余部分)。


In Raymond Hettinger's talk "Super considered super speak" at PyCon 2015 he explains the advantages of using super in Python in multiple inheritance context. This is one of the examples that Raymond used during his talk:

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')

Somebody in the audience asked Raymond about the difference of using self.get_dough() instead super().get_dough(). I didn't understand very well the brief answer of Raymond but I coded the two implementations of this example to see the differences. The output are the same for both cases:

Getting dough
Making pie with pure untreated wheat dough
Adding: Sausage
Adding: Mushroom

If you alter the class order from OrganicPizza(Pizza, OrganicDoughFactory) to OrganicPizza(OrganicDoughFactory, Pizza) using self.get_dough(), you will get this result:

Making pie with pure untreated wheat dough

However if you use super().get_dough() this is the output:

Making pie with insecticide treated wheat dough

I understand the super() behavior as Raymond explained. But what is the expected behavior of self in multiple inheritance scenario?

解决方案

Just to clarify, there are four cases, based on changing the second line in Pizza.order_pizza and the definition of OrganicPizza:

  1. super(), (Pizza, OrganicDoughFactory) (original): 'Making pie with pure untreated wheat dough'
  2. self, (Pizza, OrganicDoughFactory): 'Making pie with pure untreated wheat dough'
  3. super(), (OrganicDoughFactory, Pizza): 'Making pie with insecticide treated wheat dough'
  4. self, (OrganicDoughFactory, Pizza): 'Making pie with pure untreated wheat dough'

Case 3. is the one that's surprised you; if we switch the order of inheritance but still use super, we apparently end up calling the original DoughFactory.get_dough.


What super really does is ask "which is next in the MRO (method resolution order)?" So what does OrganicPizza.mro() look like?

  • (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'>]

The crucial question here is: which comes after Pizza? As we're calling super from inside Pizza, that is where Python will go to find get_dough*. For 1. and 2. it's OrganicDoughFactory, so we get the pure, untreated dough, but for 3. and 4. it's the original, insecticide-treated DoughFactory.


Why is self different, then? self is always the instance, so Python goes looking for get_dough from the start of the MRO. In both cases, as shown above, OrganicDoughFactory is earlier in the list than DoughFactory, which is why the self versions always get untreated dough; self.get_dough always resolves to OrganicDoughFactory.get_dough(self).


* I think that this is actually clearer in the two-argument form of super used in Python 2.x, which would be super(Pizza, self).get_dough(); the first argument is the class to skip (i.e. Python looks in the rest of the MRO after that class).

这篇关于Python self和super在多重继承中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆