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 Instant Objects Method Arguments

Leandro Severino
Leandro Severino
12,674 Points

Why is the sneaky variable outside the __init__ and Why is it declared again in the inside __init__ ?Is'nt it redundant?

import random

class Thief:

    sneaky = True

    def __init__(self,name,sneaky=True,**kwargs):
        self.name = name
        self.sneaky = sneaky
        for key, value in kwargs.items():
            setattr(self,key,value)

    def pickpocket(self):
        return self.sneaky and bool(random.randint(0,1))

    def hide(self,light_level):
        return self.sneaky and light_level < 10

5 Answers

Steven Parker
Steven Parker
231,268 Points

You're right, you don't actually need both.

Outside of __init__, you see it declared as a class attribute. Inside, the __init__ it is initialized for this specific instance, and takes precedence over the class attribute of the same name.

So in one sense you could say the declaration as a class attribute is redundant, but it can be nice to organize class attributes at the beginning of the class where they can be easily seen. But there are other ways to document attributes and I don't see any practical advantage in having the extra value.

When posting code, to make the spacing show up correctly (in Python, indentation is everything), use the instructions for code formatting in the Markdown Cheatsheet pop-up below the "Add an Answer" area. :arrow_heading_down:

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,441 Points

There is one aspect not yet covered. As Henry mentioned setting sneaky outside of methods creates a class attribute. This is different from the instance attributes defined during __init__. The instance attribute overrides the class attribute but does not alter it.

Now the instance attribute sneaky will have the value of the sneaky argument passed into the __init__ method. If not set or True, the instance attribute is True, otherwise it will be False.

Regardless of the instance attribute value, if this instance attribute gets deleted, then the class attribute would no longer be overridden and its value would then be seen in any instance references to self.value.

Other than this last (strange) usage model, I can't think of a reason to include the class attribute and initialize it as an instance attribute.

+1 To Steve,

I would add to Steve's readability explanation that whilst declaring it as a class variable and declaring it through __init__ with a default parameter value are functionally identical, they may not mean the same thing to people reading the code.

In this example, I see straight away that every instance of the class will have the class variable sneaky with a common value. I don't expect that to be overriden, so when I get to __init__ and I see there's an option to override the default value on instantiation, To me that says the default behaviour is not to override sneaky. Kind of a "you'll know it if you need to" kind of situation.

If there were no class variable, just an __init__ that has a default value for one of it's parameters, then I'm leaning more towards this is a value I would quite often set on instantiation, but I don't always need to as the __init__ will insert a default if I don't.

Of course you would hope any documentation, comments and naming have prepared the user for this, but always assume any user or developer that follows you, when presented with two routes will take the wrong one. ;)

Henry Lin
Henry Lin
11,636 Points

Hi, I would say both Jon and Steve had an excellent explanation. Here is what I want to point out:

Any attribution that created(defined) outside of any method(functions) is called class's field.

You should always initialize them in init method(which is also called constructor) and they are accessible through the whole programming.

The reason that sneaky is being declared twice here is that first time we created a class field and set the default value to True, and the second time we initialized it in init method so that every time we create Thief instance we can assign a different value to the instance. Let's say, some thieves are sneaky while some are not.

Thank you so much for your clear explanation!

Rui Xu
Rui Xu
11,245 Points

I really like the discussions in treeehouse, thank you all for the sharing here!!