简体   繁体   English

多个 class inheritance 一个祖父母,两个父母,一个孩子的类型错误 class

[英]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:这种方法遵循一些简单的规则:

  1. Every __init__ method accepts arbitrary keyword arguments via **kwargs .每个__init__方法都通过**kwargs接受任意关键字 arguments。
  2. Every __init__ method calls super.__init__(**kwargs) .每个__init__方法调用super.__init__(**kwargs)
  3. Every __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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM