Today we’re going to talk about one of the most misunderstood concepts in Python: class vs instance attributes. But first, let’s start with a little story.
Once upon a time, I was interviewing for a job and they asked me to write some code using classes. I thought it would be easy peasy lemon squeezy (as my grandma used to say) until they threw in this curveball: “Can you add a default value for an instance attribute?”
I’m like, “Uh… what? Is that even possible?” And then the interviewer said something about class attributes and I was like, “Wait, hold on. Let me Google this real quick.”
So if you’re also confused about Python attributes or just want to brush up your skills, Let’s get right into it with it!
To kick things off: what are attributes? In programming terms, an attribute is a property that describes something (like a class or object). For example, in the real world, a car has properties like make, model, and color. Similarly, in Python, classes have properties called attributes.
Now two types of attributes: class attributes and instance attributes. Class attributes are defined at the class level (outside any method) and apply to all instances of that class. Instance attributes, on the other hand, are assigned within a constructor or method and only affect one specific object (instance).
Here’s an example using our trusty car analogy: let’s say we have a Car class with two properties: make and model. We want to set a default value for the make property so that all cars created from this class will automatically have “Toyota” as their manufacturer. To do this, we add the following line at the beginning of our Car class:
# Class definition for Car
class Car(object):
make = 'Toyota' # Class attribute for default value of make property
# Constructor method for Car class
def __init__(self, model):
self.model = model # Instance attribute for model property
# Method to start the car's engine
def start_engine(self):
print("Starting engine...")
# Create an instance of Car class with model "Camry"
my_car = Car("Camry")
# Print the make and model of the car
print("Make:", my_car.make) # Prints "Toyota"
print("Model:", my_car.model) # Prints "Camry"
# Change the make of the car to "Honda"
my_car.make = "Honda"
# Print the updated make of the car
print("Make:", my_car.make) # Prints "Honda"
Now let’s create a new instance (object) of the Car class:
# Create a class called Car
class Car:
# Initialize the class with a make attribute
def __init__(self, make):
self.make = make
# Create an instance (object) of the Car class with the make 'Camry'
my_car = Car('Camry')
# Print the make attribute of the my_car object
print(my_car.make) # Output: Camry
As you can see, even though we didn’t explicitly set the make property for our my_car object, it still has a value of “Toyota” because that is the default class attribute.
But what if we want to override this default value with something else? That’s where instance attributes come in! Let’s say we have another car called my_other_car and we want its manufacturer to be Honda instead:
# Creating a class called Car
class Car:
# Defining a class attribute called "make" with a default value of "Toyota"
make = "Toyota"
# Defining a constructor method that takes in a parameter called "model"
def __init__(self, model):
# Setting an instance attribute called "model" with the value passed in as the parameter
self.model = model
# Creating an instance of the Car class called "my_other_car" with the model "Accord"
my_other_car = Car('Accord')
# Setting an instance attribute for the "make" property of "my_other_car" to be "Honda"
my_other_car.make = 'Honda'
# Printing the value of the "make" property of "my_other_car"
print(my_other_car.make) # Output: Honda
As you can see, we added a new line to set the value of the make property specifically for my_other_car object (instance). This overrides the default class attribute and gives us a customized car with “Honda” as its manufacturer.
Class vs instance attributes in Python: two peas in a pod, but with different purposes. Remember to use them wisely and don’t let your code get too carried away (like my interviewer did).