继承的 __init__() 函数未按预期工作

Inherited __init__() function not working as intended

我在 Python 上使用 pygame 库开发游戏。我基本上定义了一个 Character class,Knight class 和 Enemy class 将从中继承函数。由于两个子 class 使用相同的初始化函数,我在父 class 下定义了 __init__() 函数。但是,我不完全理解它是如何工作的,并且出现以下错误:

TypeError: __init__() takes 1 positional argument but 3 were given

这是我的代码:

class Character():

    def __init__(self, img, hitbox, vel, pos_x, pos_y):
        self.img = img
        self.hitbox = hitbox
        self.vel = vel
        self.pos_x = pos_x
        self.pos_y = pos_y
    
    def draw(self):
        
        if self.right:
            pygame.transform.flip(self.img, True, False)
        
        win.blit(self.img, (self.pos_x, self.pos_y))

class Knight(Character):
    
    def __init__(self):
        Character.__init__(self)

    def move(self):
        if self.right:
            if self.x + self.vel < win_width:
                self.x += self.vel
        if self.left:
            if self.x - self.vel > 0:
                self.x -= self.vel

main_plr = Knight("img", (19, 20), 5, 30, 20)

快速修复:只需从 Knight.

中删除 __init__ 方法

错误出现是因为你用 6 创建了一个 Knight 对象 参数 (self, "img", (19, 20), 5, 30, 20) 而 __init__ 方法只接受一个 (self).

因此,如果您的 Knight 对象没有任何附加属性 与 Character 个对象相比,删除 __init__ 方法。现在如果你想让你的骑士拥有武器,因为 例如,你将不得不做这样的事情:

class Knight(Character):

   def __init__(self, img, hitbox, vel, pos_x, pos_y, weapon):
      super().__init__(img, hitbox, vel, pos_x, pos_y)
      self.weapon = weapon

k = Knight("img", (19, 20), 5, 30, 20, "sword")

[编辑]

此外,正如@Matiiss 所建议的,您可以使用 *args 来避免 在 Knight.__init__ 中重复 Character.__init__ 的所有参数。 除了简洁之外,还有一个优点是您不必修改 Knight 如果您向 Character 对象添加属性。

class Knight(Character):

    def __init__(self, *args, weapon):
        super().__init__(*args)
        self.weapon = weapon

k = Knight("img", (19, 20), 5, 30, 20, weapon="sword")

但现在的缺点是你必须指定 weapon weapon="the-weapon",因为它现在是关键字参数(放置 在 *args).

之后

正如您看到的错误所说,您的 Knight 构造函数不接受这些参数;如果您要使用那种继承的方法扩展,class 和 subclass 方法需要具有匹配的参数签名。最好使用 super() 来引用超级 class 而不是明确命名它。

最简单的处理方法是使用*args**kwargs,将subclass方法不需要的参数简洁地传递给super[=19] =]方法,即

class Character():

    def __init__(self, img, hitbox, vel, pos_x, pos_y):
        self.img = img
        self.hitbox = hitbox
        self.vel = vel
        self.pos_x = pos_x
        self.pos_y = pos_y
    

class Knight(Character):
    
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    def move(self):
        if self.right:
            if self.x + self.vel < win_width:
                self.x += self.vel
        if self.left:
            if self.x - self.vel > 0:
                self.x -= self.vel