4.5. Working with Classes and Instances

You can use classes to represent many real-world situations. Once you write a class, you'll spend most of your time working with instances created from that class. One of the first tasks you'll want to do is modify the attributes associated with a particular instance. You can modify the attributes of an instance directly or write methods that update attributes in specific ways.

The Car Class

Let's write a new class representing a car. Our class will store information about the kind of car we're working with, and it will have a method that summarizes this information.


> At ❶ in the Car class, we define the __init__() method with the self parameter first, just like we did before with our Dog class. We also give it three other parameters: make, model, and year. The __init__() method takes in these parameters and assigns them to the attributes that will be associated with instances made from this class. When we make a new Car instance, we'll need to specify a make, model, and year for our instance.
> At ❷, we define a method called get_descriptive_name() that puts a car's year, make, and model into one string neatly describing the car (so no need to print each attribute's value individually). To work with the attributes values in this method, we use self.make, self.model, and self.year.
> At ❸, we make an instance from the Car class and assign it to the variable my_new_car. Then we call get_descriptive_name() to show what kind of car we have.

Setting a Default Value for an Attribute

When an instance is created, attributes can be defined without being passed in as parameters. These attributes can be defined in the __init__() method, where they are assigned a default value.

Let's add an attribute called odometer_reading that always starts with a value of 0. We'll also add a method read_odometer() that helps us read each car's odometer.


> This time when Python calls the __init__() method to create a new instance, it stores the make, model, and year values as attributes like it did in the previous example. Then Python creates a new attribute called odometer_reading and sets its initial value to 0 at ❶. We also have a new method called read_odometer() at ❷ that makes it easy to read a car's mileage. Our car starts with a mileage of 0.

Modifying Attribute Value

The simplest way to modify the value of an attribute is to access the attribute directly through an instance. Here we set the odometer reading to 23 directly:


> We use dot notation to access the car's odometer_reading attribute and set its value directly. In that line, Python take the instance my_new_car, find the attribute odometer_reading associated with it, and set the value of the attribute to 23.

It can be helpful to have methods that update certain attributes for you. Instead of accessing the attribute directly, you pass the new value to a method that handles the updating internally.

Here's an example showing a method called update_odometer().



> The only modification to Car is the addition of update_odometer() at ❶. This method takes in a mileage value and assigns it to self.odometer_reading.
> At ❷ we call update_odometer() and give it 23 as an argument (corresponding to the mileage parameter in the method definition). It sets the odometer reading to 23, and read_odometer prints the reading.

Sometimes you'll want to increment an attribute's value by a certain amount rather than set an entirely new value. Say we buy a used car and put 100 miles on it between the time we buy it and the time we register it. Here's a method that allows us to pass this incremental amount and add that value to the odometer reading.



> The new method increment_odometer() at ❶ takes in a number of miles, and adds this value to self.odometer_reading.
> At ❷, we create a used car, my_used_car.
> At ❸, we set its odometer to 23,500 by calling update_odometer() and passing it 23_500. Then, we call increment_odometer() and pass it 100 to add 100 miles.

Exercise 4.5

  1. Number Served
    Start with your program from Exercise 4.4.

    • Add an attribute called number_served with a default value of 0. Create an instance called restaurant from this class. Print the number of customers the restaurant has served, and then change this value and print it again.

    • Add a method called set_number_served() that lets you set the number of customers that have been served. Call this method with a new number and print the value again.

    • Add a method called increment_number_served() that lets you increment the number of customers who've been served. Call this method with any number you like that could represent how many customers were served in, say, a day of business.

  2. Login Attempts
    Add an attribute called login_attempts to your User class from Exercise 4.4.

    • Write a method called increment_login_attempts() that increments the value of login_attempts by 1.

    • Write another method called reset_login_attempts() that resets the value of login_attempts to 0.

    • Make an instance of the User class and call increment_login_attempts() several times.

    • Print the value of login_attempts to make sure it was incremented properly, and then call reset_login_attempts().

    • Print login_attempts again to make sure it was reset to 0.