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 trialLeandro Severino
12,674 PointsWhy 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
231,261 PointsYou'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.
Chris Freeman
Treehouse Moderator 68,441 PointsThere 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.
Jon Mirow
9,864 Points+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. ;)
Steven Parker
231,261 PointsAnd +1 to you, too.
Henry Lin
11,636 PointsHi, 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.
Hanna Han
4,105 PointsThank you so much for your clear explanation!
Rui Xu
11,245 PointsI really like the discussions in treeehouse, thank you all for the sharing here!!