super()如何处理多重继承?例如,给定:
class First(object):
def __init__(self):
print "first"
class Second(object):
def __init__(self):
print "second"
class Third(First, Second):
def __init__(self):
super(Third, self).__init__()
print "that's it"
Third的哪个父方法执行super()。__init__ refer to?我可以选择哪些运行吗?
我知道这与方法解析顺序(MRO)有关。
你的代码和其他答案都是错误的。它们缺少前两个类中的super()调用,这是合作子类化工作所必需的。更好的是:
class First(object):
def __init__(self):
super(First, self).__init__()
print("first")
class Second(object):
def __init__(self):
super(Second, self).__init__()
print("second")
class Third(First, Second):
def __init__(self):
super(Third, self).__init__()
print("third")
输出:
>>> Third()
second
first
third
super()调用在每一步都在MRO中查找下一个方法,这就是为什么First和Second也必须拥有它,否则执行将在Second.__init__()结束时停止。
如果在First和Second中没有super()调用,输出就会丢失Second:
>>> Third()
first
third
你的代码和其他答案都是错误的。它们缺少前两个类中的super()调用,这是合作子类化工作所必需的。更好的是:
class First(object):
def __init__(self):
super(First, self).__init__()
print("first")
class Second(object):
def __init__(self):
super(Second, self).__init__()
print("second")
class Third(First, Second):
def __init__(self):
super(Third, self).__init__()
print("third")
输出:
>>> Third()
second
first
third
super()调用在每一步都在MRO中查找下一个方法,这就是为什么First和Second也必须拥有它,否则执行将在Second.__init__()结束时停止。
如果在First和Second中没有super()调用,输出就会丢失Second:
>>> Third()
first
third
也许还可以添加一些东西,比如Django rest_framework和装饰器的一个小例子。这为隐含的问题提供了答案:“我为什么想要这个?”
如前所述:我们使用Django rest_framework,我们使用泛型视图,对于数据库中的每种类型的对象,我们发现我们有一个视图类为对象列表提供GET和POST,另一个视图类为单个对象提供GET、PUT和DELETE。
现在我们要用Django的login_required来装饰POST、PUT和DELETE。注意,这涉及到两个类,而不是两个类中的所有方法。
解决方案可以通过多重继承。
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
class LoginToPost:
@method_decorator(login_required)
def post(self, arg, *args, **kwargs):
super().post(arg, *args, **kwargs)
其他方法也是如此。
在我的具体类的继承列表,我将添加我的LoginToPost之前ListCreateAPIView和LoginToPutOrDelete之前RetrieveUpdateDestroyAPIView。我的具体类的get将保持未修饰。
在这种情况下,你试图继承的每个类都有自己的init位置参数,只需调用每个类自己的init方法,如果试图继承多个对象,则不要使用super。
class A():
def __init__(self, x):
self.x = x
class B():
def __init__(self, y, z):
self.y = y
self.z = z
class C(A, B):
def __init__(self, x, y, z):
A.__init__(self, x)
B.__init__(self, y, z)
>>> c = C(1,2,3)
>>>c.x, c.y, c.z
(1, 2, 3)
在python 3.5+中,继承看起来是可预测的,对我来说非常好。
请看下面的代码:
class Base(object):
def foo(self):
print(" Base(): entering")
print(" Base(): exiting")
class First(Base):
def foo(self):
print(" First(): entering Will call Second now")
super().foo()
print(" First(): exiting")
class Second(Base):
def foo(self):
print(" Second(): entering")
super().foo()
print(" Second(): exiting")
class Third(First, Second):
def foo(self):
print(" Third(): entering")
super().foo()
print(" Third(): exiting")
class Fourth(Third):
def foo(self):
print("Fourth(): entering")
super().foo()
print("Fourth(): exiting")
Fourth().foo()
print(Fourth.__mro__)
输出:
Fourth(): entering
Third(): entering
First(): entering Will call Second now
Second(): entering
Base(): entering
Base(): exiting
Second(): exiting
First(): exiting
Third(): exiting
Fourth(): exiting
(<class '__main__.Fourth'>, <class '__main__.Third'>, <class '__main__.First'>, <class '__main__.Second'>, <class '__main__.Base'>, <class 'object'>)
正如你所看到的,它对每个继承链调用foo一次,其顺序与继承链的顺序相同。你可以通过调用.mro来获得订单:
Fourth -> Third -> First -> Second -> Base ->对象