[英]Multiple class inheritance TypeError with one grandparent, two parents, one child class
I'm practicing OOP and keep running into this issue.我正在练习 OOP 并不断遇到这个问题。 Here's one example.
这是一个例子。
Take a diamond-shaped multiple class inheritance arrangement, with Weapon feeding Edge and Long, both of which are inherited by Zweihander.拿一个菱形倍数class inheritance排列,带Weapon feeding Edge和Long,都是双汉德继承的。 If I code Edge without inheriting Weapon, the code works fine.
如果我在不继承 Weapon 的情况下对 Edge 进行编码,则代码可以正常工作。 But as soon as I make Weapon its parent, Edge can't seem to find the argument for its 'sharpness' parameter anymore.
但是一旦我将 Weapon 作为其父级,Edge 似乎就无法再找到其“锐度”参数的参数。 It gives me a
它给了我一个
TypeError: Edge.__init__() missing 1 required positional argument: 'sharpness'
Oddly, the final line referenced by the error is the super().奇怪的是,错误引用的最后一行是 super()。 init () line in the Long class constructor.
Long class 构造函数中的init () 行。 If the eventual object I create is a Zweihander, it has Edge and gets all the Weapon elements via Long, so that's functionally acceptable.
如果我最终创建的 object 是 Zweihander,它有 Edge 并通过 Long 获取所有 Weapon 元素,所以这在功能上是可以接受的。 But if I want for instance a knife object that's just Edge, it needs to inherit Weapon, which breaks the program.
但是,如果我想要一把刀 object,它只是 Edge,它需要继承 Weapon,这会破坏程序。
What am I missing?我错过了什么? My best guess is an MRO issue, but I can't figure it out.
我最好的猜测是 MRO 问题,但我无法弄清楚。 Thanks, all.
谢谢大家
class Weapon:
def __init__(self):
self.does_damage = "very yes"
def attack(self):
print("Je touche!")
class Edge(Weapon):
def __init__(self, sharpness):
super().__init__()
self.sharpness = sharpness
class Long(Weapon):
def __init__(self, length):
super().__init__()
self.length = length
class Zweihander(Long, Edge):
def __init__(self, name, length, sharpness):
Long.__init__(self, length)
Edge.__init__(self, sharpness)
self.name = name
def warning(self):
print("I will show you...\nTHE GREATEST NIGHTMARE!!!")
soulcal = Zweihander(name="soulcal", sharpness=100, length=54)
soulcal.warning()
You only need to make a few small changes to each class's __init__
method to properly support cooperative multiple inheritance, per https://rhettinger.wordpress.com/2011/05/26/super-considered-super/您只需要对每个类的
__init__
方法进行一些小的更改即可正确支持合作多个 inheritance,根据https://rhettinger.wordpress.com/2011/05/26/super-considered-super/
class Weapon:
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.does_damage = "very yes"
def attack(self):
print("Je touche!")
class Edge(Weapon):
def __init__(self, *, sharpness, **kwargs):
super().__init__(**kwargs)
self.sharpness = sharpness
class Long(Weapon):
def __init__(self, *, length, **kwargs):
super().__init__(**kwargs)
self.length = length
class Zweihander(Long, Edge):
def __init__(self, *, name, **kwargs):
super().__init__(**kwargs)
self.name = name
def warning(self):
print("I will show you...\nTHE GREATEST NIGHTMARE!!!")
soulcal = Zweihander(name="soulcal", sharpness=100, length=54)
soulcal.warning()
This approach follows a few simple rules:这种方法遵循一些简单的规则:
__init__
method accepts arbitrary keyword arguments via **kwargs
.__init__
方法都通过**kwargs
接受任意关键字 arguments。__init__
method calls super.__init__(**kwargs)
.__init__
方法调用super.__init__(**kwargs)
。__init__
method defines keyword-only parameters instead of ordinary parameters, ensuring that keyword arguments are used at instantiation to simplify the delegation of each argument to the appropriate class.__init__
方法只定义关键字参数而不是普通参数,确保在实例化时使用关键字 arguments 以简化每个参数对适当的 class 的委托。 For example, Zweihander.__init__
has its keyword-only argument name
set by a keyword argument, with the remaining keyword arguments collected in kwargs
.例如,
Zweihander.__init__
的关键字参数name
由关键字参数设置,其余关键字 arguments 收集在kwargs
中。 It neither knows nor cares what those arguments are;它既不知道也不关心那些 arguments 是什么; it just assumes that
super().__init__
, whichever method that winds up being, will handle them appropriately.它只是假设
super().__init__
,无论最终成为哪种方法,都会适当地处理它们。
Eventually, all keyword arguments will be consumed by one of the classes in the instance's MRO, or one or more will remain in kwargs
when object.__init__
is finally called, raising a TypeError
.最终,所有关键字 arguments 将被实例的 MRO 中的一个类使用,或者当最终调用
object.__init__
时,一个或多个将保留在kwargs
中,引发TypeError
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.