Python:__init__中的继承和默认值

4 投票
2 回答
13395 浏览
提问于 2025-04-17 06:00

我正在尝试创建一个类,这个类可以接受一些通用的__init__参数,但我希望它的子类有默认值,像这样:

class Enemy:

 def __init__(self, difficulty, power, MaxHP, magic, MaxMP, speed, name):
    self.power = power + 2*difficulty
    self.HP = self.MaxHP = MaxHP + 5*difficulty
    self.magic = magic + 2* difficulty
    self.MP = self.MaxMP = MaxMP + 5*difficulty
class Goblin(Enemy):
 def __init_(self, difficulty = 1, power = 1, MaxHP = 5, magic = 1, MaxMP = 5, speed = 5, name = "Goblin"):
    super(Goblin, self).__init__(self, power, MaxHP, magic, MaxMP, speed, name)

但是,当我尝试创建一个Goblin对象,只提供一个参数(比如说,我只提供难度这个值)时,它却告诉我需要提供全部8个参数,尽管其他参数都有默认值。请问这是为什么呢?我是不是哪里做错了?

2 个回答

1

这段代码对我来说是有效的:

class Enemy(object):
    def __init__(self, difficulty, power, MaxHP, magic, MaxMP, speed, name):
        self.power = power + 2*difficulty
        self.HP = self.MaxHP = MaxHP + 5*difficulty
        self.magic = magic + 2* difficulty
        self.MP = self.MaxMP = MaxMP + 5*difficulty

class Goblin(Enemy):
    def __init__(self, difficulty = 1, power = 1, MaxHP = 5, magic = 1, MaxMP = 5, speed = 5, name = "Goblin"):
        super(Goblin, self).__init__(difficulty, power, MaxHP, magic, MaxMP, speed, name)

为了让你的代码正常工作,我做了以下几个修改:

  1. 修正了在 Goblin 中拼写错误的 def __init__
    • 症状:调用 Goblin() 时出现了 TypeError: __init__() takes exactly 8 arguments (1 given) 的错误,因为 Goblin 没有定义 __init__ 方法,所以它继承了 Enemy 中没有默认值的那个方法。
  2. 通过从 object 继承,将 Enemy 改为新式类。
    • 症状:在调用 super() 时,我遇到了 TypeError: must be type, not classobj 的错误;我不确定旧版本的 Python 是否允许这样做,或者会出现不同的错误,但我知道旧式类和新式类的 MRO(方法解析顺序)规则是不同的,我认为这可能会让 super 出现问题。
  3. 在调用 super(Goblin, self).__init__(self, ...) 时,去掉第二个 self
    • 症状:self 会自动传递给 super(Class, self).some_method(...),所以自己再放一个 self 就像是调用 Enemy.__init__(self, self, difficulty, power, ...) 一样。
  4. 在调用 super(Goblin, self).__init__(...) 时,添加了 difficulty
    • 症状:你在 Goblin.__init__ 中得到了 difficulty 的默认值,但没有把这个值传递给 Enemy.__init__

我想大概就是这些了。

5

因为你在调用 super(Goblin, self).__init__(self, power, MaxHP, magic, MaxMP, speed, name) 时没有传入 difficulty。你可能还想像这样继承 class Enemy(object),这样可以确保 Enemy 是一个新式类,如果你使用的是 2.x 版本的话(我猜你一定是,因为你用的 super 的方式比较旧)。

这里有个更简单的例子:

class Animal(object):
  def __init__(self, talk):
    print '__init__ Animal: ', talk

class Cat(Animal):
  def __init__(self, talk='meow'):
    print '__init__ Cat'
    super(Cat, self).__init__(talk)

if __name__ == '__main__':
  tom = Cat()

输出结果:

__init__ Cat
__init__ Animal:  meow

补充:

如果下面的代码还是不行,可能是因为你的解释器里缓存了旧的类定义(试着在一个新的解释器上运行看看)。

class Enemy(object):
  def __init__(self, difficulty, power, MaxHP, magic, MaxMP, speed, name):
    self.power = power + 2*difficulty
    self.HP = self.MaxHP = MaxHP + 5*difficulty
    self.magic = magic + 2* difficulty
    self.MP = self.MaxMP = MaxMP + 5*difficulty
    print 'Raaarghh!! I am the formidable {}.'.format(name)

class Goblin(Enemy):
  def __init__(self, difficulty=1, power=1, MaxHP=5, magic=1, MaxMP=5, speed=5, name="Goblin"):
    super(Goblin, self).__init__(difficulty, power, MaxHP, magic, MaxMP, speed, name)

if __name__ == '__main__':
  g = Goblin(name='user1038783 goblin')

撰写回答