所以,我有这样的情况。
class A(object):
def foo(self, call_from):
print "foo from A, call from %s" % call_from
class B(object):
def foo(self, call_from):
print "foo from B, call from %s" % call_from
class C(object):
def foo(self, call_from):
print "foo from C, call from %s" % call_from
class D(A, B, C):
def foo(self):
print "foo from D"
super(D, self).foo("D")
d = D()
d.foo()
代码的结果是
foo from D
foo from A, call from D
我想调用所有父方法,在本例中为foo方法,来自D
类,而不使用像A
这样的父类。我只想打电话给D
班的超级。 A
,B
和C
类就像mixin类,我想从D
调用所有foo方法。我怎样才能实现这一目标?
你可以像这样使用__bases__
class D(A, B, C):
def foo(self):
print "foo from D"
for cls in D.__bases__:
cls().foo("D")
通过此更改,输出将是
foo from D
foo from A, call from D
foo from B, call from D
foo from C, call from D
除了super()
之外,还可以在其他类中添加C
调用。因为D的MRO是
>>> D.__mro__
(<class '__main__.D'>, <class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <type 'object'>)
你不需要在C
超级电话。
码:
class A(object):
def foo(self, call_from):
print "foo from A, call from %s" % call_from
super(A,self).foo('A')
class B(object):
def foo(self, call_from):
print "foo from B, call from %s" % call_from
super(B, self).foo('B')
class C(object):
def foo(self, call_from):
print "foo from C, call from %s" % call_from
class D(A, B, C):
def foo(self):
print "foo from D"
super(D, self).foo("D")
d = D()
d.foo()
输出:
foo from D
foo from A, call from D
foo from B, call from A
foo from C, call from B
我相信在子类中调用super
更像是Pythonic方法。一个人不必使用父类名(特别是在super中)。在前面的例子中详细说明,这里有一些应该工作的代码(python 3.6+):
class A:
def foo(self, call_from):
print(f"foo from A, call from {call_from}")
super().foo('A')
class B:
def foo(self, call_from):
print(f"foo from B, call from {call_from}")
super().foo('B')
class C(object):
def foo(self, call_from):
print(f"foo from C, call from {call_from}")
super().foo('C')
class StopFoo:
def foo(self, call_from):
pass
class D(A, B, C, StopFoo):
def foo(self, call_from):
print(f"foo from D, call from {call_from}")
super().foo('D')
如果您运行此代码:
d = D()
d.foo('D')
你会得到:
foo from D, call from D
foo from A, call from D
foo from B, call from A
foo from C, call from B
这个策略的优点是你不必担心继承顺序,因为你包含了StopFoo
类。这个有点特殊,可能不是完成这项任务的最佳策略。基本上,继承树中的每个类都调用foo
方法并调用父方法,该方法也是如此。我们可能在谈论多重继承,但是继承树实际上是平的(D - > A - > B - > C - > Stopfoo - > object)。我们可以改变继承的顺序,为这个模式添加新类,删除它们,只需调用一个类......但诀窍仍然存在:在调用StopFoo
之前包含foo
会离开我们定义的类。
对于带钩子的mixin图案,这可能有意义。但是,当然,解决方案在每种情况下都没有那么有用。不要害怕super
,它有很多技巧,可以用于简单和多重继承,使用mixins或简单的抽象类。