Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Python Object-Oriented Python (retired) Inheritance Subclasses

Drew Butcher
Drew Butcher
33,160 Points

Overwriting an attribute in a subclass

In this example if I want to set the class Dragon to have an attribute color of say "orange" then when we create an instance of Dragon we still get a random choice from COLORS.

It seems like we should have set color = random.choice(COLORS) before the def init. This way we could overwrite the color attribute in a subclass.

Is this correct?

3 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,454 Points

There are a few ways to get all of your Dragons to be orange.

You could initiate Dragon with a keyword argument

The base class Monster takes keyword arguments. This bit of code in Monster.__init__():

    for key, value in kwargs.items():
        setattr(self, key, value)

takes any keyword argument and sets it as an attribute of the class after it runs the basic initialization and random color assigment. So you could simply instatiate your Dragon using:

    orangy_the_dragon = Dragon(color='orange')

You could write your own Dragon.__init__() method that overwrites the Monster.__init__ () method:

class Dragon(Monster):
    min_hit_points = 5
    max_hit_points = 10
    min_experience = 6
    max_experence = 10
    sound = "raaaaaaaaaaar"

    def __init__(self):
        self.hit_points = random.randint(self.min_hit_points, self.max_hit_points)
        self.experience = random.randint(self.min_experience, self.max_experience)
        color = 'orange'  # <-- hard set color
        # keep keyword argument parsing to allow overwriting color (if you tire of orange)
        for key, value in kwargs.items():
            setattr(self, key, value)

But this isn't very DRY: you're repeating code from the Monster base class

You could write your own Dragon.__init__() method that utilizes the Monster.__init__ () method:

class Dragon(Monster):
    min_hit_points = 5
    max_hit_points = 10
    min_experience = 6
    max_experence = 10
    sound = "raaaaaaaaaaar"

    def __init__(self, **kwargs):
        # call base class __init__()
        super(Dragon, self).__init__(**kwargs)
        color = 'orange'  # <-- hard set color

At Dragon instantiation, __init__() is called to initialize the new instance. If Dragon doesn't define it's own __init__(), Monster.__init__()' is called. As you found out, definingcoloras a base attribute ofDragongets overwritten byMonster.init()`.

Your suggestion of moving the random color assignment from Monster.__init__() to a Monster base attribute would have an undesired side effect: All monsters of the same subclass of Monster will have the same color since the color would be defined once, randomly, when the class is first parsed. Color would not be redefined each time a new instance is created unless the instance color is define using a keyword argument.

Drew Butcher
Drew Butcher
33,160 Points

Cool and I like the info about how all the monster of the same subclass (like Goblins) will have the same color.... All my Goblins turned out Red :(

Kenneth Love
STAFF
Kenneth Love
Treehouse Guest Teacher

OO is a fun and constantly surprising school of programming. Some things work just...perfectly. Exactly like you expect them to. And then sometimes you couldn't be more lost between inheritance and everything else.