emufossum13
emufossum13

Reputation: 407

Invoking base methods in classes

I'm working on a game, and one of the things I want to do is to have a base class that defines an attribute damage, and uses a constructor to initiate that value. This is my base class

class Weapon(object):
def __init__(self, damage):
    self.damage = damage

This is the actual class that calls on Weapon for the game

class Crossbow(Weapon):
is_loaded = True
reloads = 5
def __init__(self, is_loaded, reloads):
    super(Crossbow, self).__init__()
    self.is_loaded = is_loaded
    self.reloads = reloads

def reload(self):
    print "You need to reload, before you can fire again"
    time.sleep(2)
    if reloads > 0:
        print "Reloading bow"
        time.sleep(2)
        reloads -= 1
        is_loaded = True
        print "Successfully reloaded bow"
        time.sleep(1)
        print "You now have",reloads,"arrow left"
        time.sleep(2)
    else:
        print "You don't have any more arrows"
        time.sleep(2)

I was testing the reload function using:

c = Crossbow(Weapon)
for i in range(1,6):
    c.reload()

The reason I run the class method 6 times, is that I wanted to test the reload variable which counts how many times you reload. It subtracts each time it counts, and once it reaches zero, it doesn't let you reload, so 6 times would be able to test the full functionality. However, when I run that block of code, I get this error:

me.py", line 47, in <module>
c = Crossbow(Weapon)
TypeError: __init__() takes exactly 3 arguments (2 given)

I've used classes before, but I'm new to creating a base class and constructor and calling other classes off of that. If someone could help me understand my problem, I would very much appreciate it.

Upvotes: 0

Views: 166

Answers (2)

Peter DeGlopper
Peter DeGlopper

Reputation: 37319

When you specify a positional argument to your class's __init__ method, that means you're committing to passing in the arguments each time you instantiate the class. Because you've declared is_loaded and reloads as positional arguments to your Crossbow class's __init__ method, you must provide them when instantiating. In your testing code, you're providing the class Weapon as the value of your __init__ call's first positional paramater, is_loaded. This is, of course, wrong, but not a syntax error. You're not providing any argument at all for reloads, and that is a syntax error.

You may wish to set default values for the arguments which will be used if not provided, eg:

def __init__(self, is_loaded=True, reloads=5):
    super(Crossbow, self).__init__(damage=5) # or whatever for damage

If you do that, you can instantiate without explicitly setting the values.

You could also set the default values to None and only override the class's values on a non-None value:

def __init__(self, is_loaded=None, reloads=None):
    super(Crossbow, self).__init__(damage=5)
    if is_loaded is not None:
        self.is_loaded = is_loaded
    if reloads is not None:
        self.reloads = reloads

Upvotes: 1

user2357112
user2357112

Reputation: 280251

You create an instance of Crossbow with c = Crossbow(initial_load_state, initial_reloads), not c = Crossbow(Weapon). (Also, your superclass constructor call is missing a damage argument.)

Upvotes: 0

Related Questions