4

I am trying to make a class with generic __init__ values, but have defaults for its subclasses, as so:

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)

However, when I try to make a Goblin object without the full number of default values (like, I'll just put in a value for difficulty), it tells me I need the full 8 arguments even though the rest are given default values. Is there any reason I can't do that or am I doing something wrong here?

1
  • 3
    You're missing an underscore from Goblin's __init__. So you should copy and paste the code that is causing the problem. And the full traceback, too. Python's tracebacks are usually very helpful. Commented Nov 10, 2011 at 1:02

2 Answers 2

5

Because you called super(Goblin, self).__init__(self, power, MaxHP, magic, MaxMP, speed, name) without difficulty. You probably also want to inherit like class Enemy(object) to make sure Enemy is a new-style class if you're on 2.x (which I guess you must be, considering the old way that you've used super).

Here's a simpler example:

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()

Outputs :

__init__ Cat
__init__ Animal:  meow

Edit:

Well if the following doesn't work, perhaps you have old class definitions cached in your interpreter (try running it on a fresh interpreter).

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')
Sign up to request clarification or add additional context in comments.

4 Comments

Hah, the things you miss when you think you tried everything. And thank you for the Object part.
I tried running the program again (as opposed to my test driver), and even with difficulty there I still get the same error "TypeError: init takes exactly 8 arguments, 2 given"
OK, check the double underscore in the __init__ , and don't pass in self explicitly because it gets done implicitly.
The __init__() was spelled correctly, and I tried all combos of removing the self from (Goblin, self) and (self, difficulty, power...), and I still have the same error.
1

This code works for me:

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)

The ways I had to change yours to get it to work:

  1. Fix misspelled def __init__ in Goblin.
    • Symptom: Goblin() raised TypeError: __init__() takes exactly 8 arguments (1 given), as Goblin had not defined an __init__ method, so it had inherited the one without defaults from Enemy
  2. Change Enemy into a new-style class by inheriting from object
    • Symptom: I got TypeError: must be type, not classobj on the call to super(); I'm not sure whether older versions of Python would have allowed it or triggered a different error, but I know old-style classes have different MRO (method resolution order) rules than new-style classes, and I believe this could make super screwy anyway.
  3. Remove the second self from the call to super(Goblin, self).__init__(self, ...)
    • Symptom: self is automatically passed to super(Class, self).some_method(...), so putting it in there yourself is like calling Enemy.__init__(self, self, difficulty, power, ...).
  4. Added difficulty to the call to super(Goblin, self).__init__(...)
    • Symptom: You were getting difficulty defaulted in Goblin.__init__, but then not passing the value up to Enemy.__init__.

I think that was about it.

1 Comment

Ah yes, wim mentioned the init being mistyped but I missed that again when I checked it over. Thanks to both of you, it's working now.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.