pythonsuper多重继承_Python多重继承:在所有上调用super

我有以下两个超类:

class Parent1(object):

def on_start(self):

print('do something')

class Parent2(object):

def on_start(self):

print('do something else')

我希望有一个继承的子类可以为父母双方打电话.

class Child(Parent1, Parent2):

def on_start(self):

# super call on both parents

什么是Pythonic的方法呢?谢谢.

解决方法:

执行摘要:

Super只执行一个基于类层次结构__mro__的方法.如果要使用相同的名称执行多个方法,则需要编写父类来协同执行(通过隐式或显式调用super)或者需要循环__bases__或子类的__mro__值.

super的工作是将方法调用的部分或全部委托给类祖先树中的某个现有方法.代表团可能会在您控制的课程之外进行.委派的方法名称需要存在于基类组中.

使用带有try / except的__bases__下面给出的方法最接近于如何调用每个父对象的同名方法的问题的完整答案.

super在你想要调用父方法之一的情况下很有用,但你不知道哪个父方法:

class Parent1(object):

pass

class Parent2(object):

# if Parent 2 had on_start - it would be called instead

# because Parent 2 is left of Parent 3 in definition of Child class

pass

class Parent3(object):

def on_start(self):

print('the ONLY class that has on_start')

class Child(Parent1, Parent2, Parent3):

def on_start(self):

super(Child, self).on_start()

在这种情况下,Child有三个直接的父母.只有一个Parent3具有on_start方法.调用super解析只有Parent3具有on_start并且这是被调用的方法.

如果Child从多个具有on_start方法的类继承,则从左到右(如类定义中所列)和从下到上(作为逻辑继承)解析顺序.只调用其中一个方法,并且已取代类层次结构中的其他同名方法.

所以,更常见的是:

class GreatGrandParent(object):

pass

class GrandParent(GreatGrandParent):

def on_start(self):

print('the ONLY class that has on_start')

class Parent(GrandParent):

# if Parent had on_start, it would be used instead

pass

class Child(Parent):

def on_start(self):

super(Child, self).on_start()

如果要按方法名称调用多个父方法,则可以在这种情况下使用__bases__而不是super,并在不知道类名的情况下迭代Child的基类:

class Parent1(object):

def on_start(self):

print('do something')

class Parent2(object):

def on_start(self):

print('do something else')

class Child(Parent1, Parent2):

def on_start(self):

for base in Child.__bases__:

base.on_start(self)

>>> Child().on_start()

do something

do something else

如果有可能其中一个基类没有on_start,则可以使用try / except:

class Parent1(object):

def on_start(self):

print('do something')

class Parent2(object):

def on_start(self):

print('do something else')

class Parent3(object):

pass

class Child(Parent1, Parent2, Parent3):

def on_start(self):

for base in Child.__bases__:

try:

base.on_start(self)

except AttributeError:

# handle that one of those does not have that method

print('"{}" does not have an "on_start"'.format(base.__name__))

>>> Child().on_start()

do something

do something else

"Parent3" does not have an "on_start"

使用__bases__将类似于super,但对于Child定义中定义的每个类层次结构.也就是说,它将通过每个forbearer类,直到on_start为该类的每个父级满足一次:

class GGP1(object):

def on_start(self):

print('GGP1 do something')

class GP1(GGP1):

def on_start(self):

print('GP1 do something else')

class Parent1(GP1):

pass

class GGP2(object):

def on_start(self):

print('GGP2 do something')

class GP2(GGP2):

pass

class Parent2(GP2):

pass

class Child(Parent1, Parent2):

def on_start(self):

for base in Child.__bases__:

try:

base.on_start(self)

except AttributeError:

# handle that one of those does not have that method

print('"{}" does not have an "on_start"'.format(base.__name__))

>>> Child().on_start()

GP1 do something else

GGP2 do something

# Note that 'GGP1 do something' is NOT printed since on_start was satisfied by

# a descendant class L to R, bottom to top

现在想象一个更复杂的继承结构:

如果你想要每个onbearer的on_start方法,你可以使用__mro__并过滤掉那些没有on_start的类,作为该类的__dict__的一部分.否则,你可能会得到一个onbearer的on_start方法.换句话说,hassattr(c,’on_start’)对于Child是其后代的每个类都是True(在这种情况下除了对象),因为Ghengis有一个on_start属性,所有类都是Ghengis的后代类.

**警告 – 仅限演示**

class Ghengis(object):

def on_start(self):

print('Khan -- father to all')

class GGP1(Ghengis):

def on_start(self):

print('GGP1 do something')

class GP1(GGP1):

pass

class Parent1(GP1):

pass

class GGP2(Ghengis):

pass

class GP2(GGP2):

pass

class Parent2(GP2):

def on_start(self):

print('Parent2 do something')

class Child(Parent1, Parent2):

def on_start(self):

for c in Child.__mro__[1:]:

if 'on_start' in c.__dict__.keys():

c.on_start(self)

>>> Child().on_start()

GGP1 do something

Parent2 do something

Khan -- father to all

但是这也存在一个问题 – 如果Child被进一步子类化,那么Child的孩子也会循环遍历同一个__mro__链.

如Raymond Hettinger所述:

super() is in the business of delegating method calls to some class in

the instance’s ancestor tree. For reorderable method calls to work,

the classes need to be designed cooperatively. This presents three

easily solved practical issues:

1) the method being called by super() needs to exist

2) the caller and callee need to have a matching argument signature and

3) every occurrence of the method needs to use super()

解决方案是编写合作类,通过祖先列表或adapter pattern的创​​造性使用统一使用super来适应您无法控制的类. Raymond Hettinger在文章Python’s super() considered super!中更全面地讨论了这些方法.

标签:python

来源: https://codeday.me/bug/20191004/1853158.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值