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) Objects __init__

I don't recall learning about overriding methods thus far. I get an error about Task 1 not passing.

This is what I entered into the interpreter:

class Student(): name = "Joe" def init(self, **kwargs): self.name = kwargs.get('name','')

So I was thinking I could instantiate this class with a student name as follows:

my_student = Student(name='Frank')

and then my_student.name would be 'Frank' but I didn't get this far due to the error about Task 1 not passing.

student.py
class Student():
    name = 'Adiv'

4 Answers

The code you have for the 2nd task is defining the student's name as an empty string.

Try this

self.name = kwargs.get('name','Joe')

Thank you. So then we must always assign a non zero length string to the self.name property? We cannot have an instance of the Student() class with name = ''?

For this exercise, yes, it appears that every instance of Student() must have a non zero length string to the self.name property.

Speaking generally, there was nothing wrong with your original code. However the exercise has a rule that every student has a non-zero length name.

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

Jesse Fisher is exactly right. Python doesn't care if you have a length to the value in a variable or not, but my CC expects there to be a fallback behavior, which that second argument provides.

Thanks for the clarification. I will try again with a default value that isn't a zero length string. Is it correct that the name property (attribute, member, field etc) just under the class header is a class level variable whereas self.name is a completely separate instance level variable? Thanks

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

Well, sorta :) This is one of the fun areas of Python. Let's set something up.

class Animal:
    species = "canine"

    def get_type(self):
        return self.species


dog = Animal()
cat = Animal()
cat.species = "feline"
Animal.species = "fox"

Now, if self.species in get_type() was always an instance-level variable, when I do dog.get_type(), I'd get back "canine", since that is what it was set to when the instance was instantiated.

But since Python doesn't hold onto more information than it needs, I'll get back "fox".

What happens is Python ask's dog if dog.__dict__ has a key named species. It doesn't, because we didn't set one on the instance either manually or in __init__(), so Python goes to dog's immediate class and asks for that class's species key from its __dict__. That just happens to currently be "fox", so that's what comes out.

99% of the time, this isn't an issue (really, how often do you think you'll change class-level attributes during execution?) but it's good to know about.

Thank you for providing an example to illustrate the concepts at work here. It would seem that to help reduce confusion, instance variables (self.xxx) should not have the same identifiers as class variables. So in this case the class variable might be renamed to class_species so that it can't be confused with the instance variable self.species. Is it standard practice to make sure class variable names are always dissimilar to instance variable names?

Kenneth Love
Kenneth Love
Treehouse Guest Teacher

No, they should be named the same. 99.99999% of the time, you don't care what the class decides a variable is because you're working only with instances. Using the same name reduces clutter, memory footprint, and makes it obvious what relates to what. Class attributes are generally placeholders or defaults, not real world, useful values.

Thank you. That really makes things much clearer for me. I have seen in other languages where a class variable is used as a counter to track the number of instances by incrementing its value when a new object from that class is instantiated.

I tried to do that in the _init method of an Employee() class I created. I found out the hard way that to increment the class variable employee_count you can't just put employee_count += 1 or even self.employee_count += 1 in the init method. The first way throws an error "UnboundLocalError: local variable 'employee_count' referenced before assignment" while the second way doesn't raise an error but doesn't appear to update the class variable employee_count

I discovered that to reference a class variable, at least inside a function, you need to use the name of the class itself, e.g. Employee.employee_count += 1.

In another thread you showed how to do the same thing with self.class.employee_count += 1 from within the class or myEmployee.class.employee_count += 1 when using an object created from that class. Thanks!