Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Adding an Instance Method

00:00 The task was to add an instance method called .drive() that takes some miles as an argument. Then that should increment self.mileage for how many miles you passed in and then test it. So I want to define .drive(), and this instance method won’t be a special method like the first two with the double underscores.

00:27 But this is just a method that is public to the Car class and that I’m going to define now. And still, it takes self as its first argument because I want to do something on the instance of the Car, and then it also takes another argument.

00:42 So I put in the parameter miles in the method definition, and that just means that when calling Car.drive(), you have to pass in miles. That’s going to be a number. And then what do you want to do with this?

00:56 You want to increment self.mileage. So because you’re passing self here and because this is a method on an instance of a Car, you have access to this self object.

01:08 So I can say self.mileage and then just increment it. So I’m going to say += miles. So this is going to take the miles that someone passes when calling .drive() and adds it to self.mileage.

01:24 And you can also do just = self.mileage + miles. That’s the same. But I’m going to go for the shorter version. This is a shortcut to saying .self.mileage + miles.

01:42 I think that should be it. Let’s go ahead and test it. So I will press F5, run it, and go into the interactive console. And then I’m just going to call it car.

01:57 Car() and it will be "blue"

02:01 and have 0 miles. Actually, just for fun, this car is going to be "white", 0 miles. Okay, so we have this Car object. If I print(car), The white car has 0 miles. And now I should be able to say car.drive().

02:20 I’m going to drive this car for a hundred miles, no output. But something happened in here because now if I print(car), it tells me that The white car has 100 miles. So with this instance method here, with .drive(), I accessed an instance attribute, .mileage, and changed it basically with whatever I input here as an argument. So that works.

02:46 I can continue driving the white car, .drive() for, let’s drive it for another a hundred miles, and then it should

02:57 have 200 miles on there. Perfect.

03:02 So good job if you came up with something similar to this, and if you have a different solution, post it in the comments. I’m curious to see.

Avatar image for DimaG

DimaG on Oct. 19, 2023

This is my version of the Car class written using dataclass syntax and operator.methodcaller():

from dataclasses import dataclass
from operator import methodcaller

@dataclass(slots=True, kw_only=True)
class Car:
    """Class representing car."""

    color: str
    mileage: int

    def __str__(self):
        """Returns string representation of car."""
        return f"The {self.color} car has {self.mileage:,} miles."

    def drive(self, miles: int) -> None:
        self.mileage += miles

blue_car = Car(color="blue", mileage=20_000)
red_car = Car(color="red", mileage=30_000)
white_car = Car(color="white", mileage=0)

cars = [blue_car, red_car, white_car]
get_mileage = methodcaller("drive", 100)
get_more_mileage = methodcaller("drive", 100)

for car in cars:
    get_mileage(car)
    print(car)

print()

for car in cars:
    get_more_mileage(car)
    print(car)
Avatar image for Martin Breuss

Martin Breuss RP Team on Oct. 25, 2023

@DimaG thanks for sharing your code using a dataclass and the operator module! :D

Two small notes:

You don’t need get_more_mileage(), it has the same functionality as get_mileage, so you could skip that and just call get_mileage() another time in your second for loop.

Secondly, I’d say that get_mileage() isn’t a very descriptive name for the functionality that you’re encoding here. You’re creating a callable that’ll call .drive() with an argument of 100. Can you come up with a more descriptive name for it?

Nice work expanding on the topics taught in the course! 🙌

Avatar image for Anonymous

Anonymous on Feb. 18, 2024

Here is my version of the challenge:

from random import uniform

class Car:

    def __init__(self,
                 make_car: str,
                 model_car: str,
                 year: int,
                 color: str,
                 mileage: float,
                 ) -> None:
        self.make_car = make_car
        self.model_car = model_car
        self.year = year
        self.color = color
        self.mileage = mileage


    def start(self):
        print(f'Starting {self.make_car} {self.model_car}...')

    def stop(self):
        print(f'{self.model_car} stopped...')

    def drive(self, distance: float) -> None:
        if Car.validate_float(distance, True):
            previous_mileage = self.mileage
            self.mileage += distance
            return (
                f'\tCurrent mileage {previous_mileage:,}km.\n'
                f'\tNew mileage {self.mileage:,}km.'
                )
        else:
            raise ValueError('Incorrect mileage has been given!')

    @staticmethod
    def validate_float(value: float, is_positive: bool=False) -> bool:
        '''if used in the Car Class, validate if distance is not <= 0
           for general use, return false if value is not an instance of type(float)'''
        if isinstance(value, float):
            if is_positive:
                return True if value > 0 else False
            else:
                return True
        else:
            return False


    def __str__(self):
        return f'The {self.color} car has {self.mileage:,}km.'


ford = Car('Ford', 'Ranger', 2014, 'blue', 20_000)
citroen = Car('Citroën', 'Vision', 2030, 'red', 30_000,)

car_obj_mapping = {
    'ford': ford,
    'citroen': citroen,
}
entered_car_brands = set()

for i in range(2):

    while True:
        get_car_brand = input('Car brand: ')
        if get_car_brand in entered_car_brands:
            print(f'{get_car_brand} has already been driven!')
            continue
        elif car_obj_mapping.get(get_car_brand, None):
            entered_car_brands.add(get_car_brand)
            car_obj_mapping[get_car_brand].start()
            break
        else:
            print(f'{get_car_brand} not recognized as a car brand!')

    random_distance = round(uniform(1, 500), 2)

    print(f'{ford.drive(random_distance)}')

    car_obj_mapping[get_car_brand].stop()
else:
    print('Test Drive complete!')
Avatar image for Anonymous

Anonymous on Feb. 18, 2024

Forgot to also change the last line:

# from
print(f'{ford.drive(random_distance)}')

# to
print(f'{car_obj_mapping[get_car_brand].drive(random_distance)}')

Become a Member to join the conversation.