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 Master Class

Why we need to set the laps inside the __init__ function?

class RaceCar:

    def __init__(self, color, fuel_remaining, laps = 0,**kwargs):
        self.color = color
        self.fuel_remaining = fuel_remaining
        self.laps = laps


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

    def run_lap(self, length):
        self.fuel_remaining = self.fuel_remaining - (length * 0.125)       
        self.laps += 1             

and in this example, it passes task 2, why we use self to increase the laps if laps it's a global var?

racecar.py
class RaceCar:
    laps = 0
    def __init__(self, color, fuel_remaining, **kwargs):
        self.color = color
        self.fuel_remaining = fuel_remaining

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

    def run_lap(self, length):
        self.fuel_remaining = self.fuel_remaining - (length * 0.125)       
        self.laps += 1             

2 Answers

Chris Freeman
MOD
Chris Freeman
Treehouse Moderator 68,441 Points

It's a case of convenient logic, you don't have to set self.laps within __init__... but the code is more readable if local attributes are initialized in the __init__ method. The attribute laps will become local once the run_lap method is executed. See below.

The "global" laps is really the class attribute RaceCar.laps. If it is changed in the class, then all instances would see the same value. However, in Python, assigning a attribute creates a local version:

>>> class RaceCar:
...     laps = 0
....    
...     def __init__(self, color, fuel_remaining, **kwargs):
...         self.color = color
...         self.fuel_remaining = fuel_remaining
...         for attr, value in kwargs.items():
...             setattr(self, attr,value)
....    
...     def run_lap(self, length):
...         self.fuel_remaining = self.fuel_remaining - (length * 0.125)       
...         self.laps += 1
... 
>>> car1 = RaceCar('blue', 10, driver='speedy')
>>> car2 = RaceCar('red', 15, driver='Rex')
>>> car1.laps
0  # points to class attribute
>>> car2.laps
0  # points to class attribute
>>> car1.run_lap(5)
>>> car1.laps
1  # This is now local to instance and not affected by RaceCar.laps
# note this should probably been 5, but run_lap is ignoring length

# check car 2 value is unchanged
>>> car2.laps
0  # still points to class attribute

# set attribute at the class level
>>> RaceCar.laps = 1000  # This is the value used if the instance does NOT have it set locally
>>> car1.laps
1  # unchanged since set locally

# check car2
>>> car2.laps
1000  # it is value of class attribute
# run lap for car2
>>> car2.run_lap(1)
>>> car2.laps
1001  # This value is now local

# Set class attribute back to 0
>>> RaceCar.laps = 0
# new car 3
>>> car3 = RaceCar('green', 10)
>>> car3.laps
0  # class attribute
>>> car3.run_lap(1)
>>> car4.laps
1  # local attribute

Using self is required to point to the attribute in the instance. If you wanted all run_lap methods to point to the same class attribute RaceCar.laps then a classmethod would need to be declared. The classmethod point to the class attributes and not the instance attributes.

>>> class RaceCar:
...     laps = 0
...     def __init__(self, color, fuel_remaining, **kwargs):
...         self.color = color
...         self.fuel_remaining = fuel_remaining
...         for attr, value in kwargs.items():
...             setattr(self, attr,value)
...     @classmethod    
...     def run_lap(cls, length):
...         cls.laps += 1
... 
>>> new_car1 = RaceCar("black", 100)
>>> new_car2 = RaceCar("purple", 150)
>>> 
>>> new_car1.laps
0
>>> new_car2.laps
0
>>> new_car2.run_lap(1)  # affects both cars
>>> new_car1.laps
1
>>> new_car2.laps
1
>>> new_car1.run_lap(1)  # affects both cars
>>> new_car1.laps
2
>>> new_car2.laps
2

Post back if you need more help. Good luck!

Chris Freeman
Chris Freeman
Treehouse Moderator 68,441 Points

This would be better as a comment under the original post.