Class Vs. Instance Variables in Python 3
Share
When learning object oriented programming in Python, there can be a few gotchas when it comes to distinguishing between class and instance variables. In this guide I’ll explain the difference between class and instance variables and provide examples demonstrating various use cases.
1 – Class vs. instance variables
First, a quick review if you’re new to object-oriented programming. A class is a template for creating objects, and an instance is the object itself. Classes often represent something in the real world, so imagine if you wanted to represent a classroom full of students. You might create a class called Student, which is a template that defines various attributes of a student. Each student, then, is an instance of the Student class.
When dealing with any sort of data, some attributes are going to be unique and some will be shared. Consider our student example, each student in this classroom has the same room number and the same teacher, but they each have a unique name, age, and favorite subject.
Class variables
Class variables are usually variables that are shared by all instances. And they are defined like this:
class Student:
teacher = 'Mrs. Jones' # class variable
Each instance of the class will have the same value for these variables:
tom = Student()
susan = Student()
print(tom.teacher)
>> "Mrs. Jones"
print(susan.teacher)
>> "Mrs. Jones"
Instance variables
Instance variables (also called data attributes) are unique to each instance of the class, and they are defined within a class method, like this:
class Student:
teacher = 'Mrs. Jones' # class variable
def __init__(self, name):
self.name = name # instance variable
See how each instance now contains a unique value for name:
tom = Student('Tom')
susan = Student('Susan')
print(tom.name)
>> "Tom"
print(susan.name)
>> "Susan"
Summary
This was only a basic overview of class and instance variables. We’ll go into more depth in the upcoming steps, but the most important takeaway is that class variables are typically used for values that are shared among all instances of a class while instance variables are used for values that are unique to each instance.
2 – What to expect from class variables
Class variables are shared among all instances of a class. As a reminder, they are defined like this:
class Student:
teacher = 'Mrs. Jones' # class variable
Said another way, class variables reference the same location in memory. See the following:
tom = Student()
susan = Student()
id(tom.teacher) == id(susan.teacher)
>> True
Note: The id
function returns the address of the object in memory for the CPython implementation.
So with the id
function we can confirm that the teacher
attribute refers to the same location in memory.
3 – Modifying a class variable
What happens if we modify a class variable even after we’ve created instances?
tom = Student()
tom.teacher
>> Mrs. Jones
Student.teacher = 'Mr. Smith'
tom.teacher
>> Mr. Smith
As you might expect, because the teacher
variable refers to a shared location in memory, it is updated on the instance as well.
4 – Modifying an instance variable
This is probably the most obvious and expected behavior, so feel free to skip past this step. But I will still show a few examples for completeness.
Consider our Student
class with both class and instance variables:
class Student:
teacher = 'Mrs. Jones' # class variable
def __init__(self, name):
self.name = name # instance variable
We can see that each instance of the class has a unique memory address for name
:
tom = Student('Tom')
susan = Student('Susan')
id(tom.name) == id(susan.name)
>> False
So as you might expect, updating the name attribute on one instance has no effect on the other:
tom,name
>> Tom
susan.name
>> Susan
tom.name = 'Thomas'
tom.name
>> Thomas
susan.name
>> Susan
5 – Instance variables override class variables (and methods)
It is important to note that instance variables (or data attributes) override class variables.
Remember the following?
tom = Student()
susan = Student()
id(tom.teacher) == id(susan.teacher)
>> True
What happens if we change the teacher
attribute directly on one of the instances:
tom.teacher = 'Mr. Clark'
This is important to note: instance variables need not be declared, they are created whenever they are assigned, and instance variables override class variables. This means, on the tom
instance, teacher
no longer refers to the class variable, but rather a newly created instance variable.
And naturally, the susan
instance is not affected:
tom.teacher # instance variable
>> Mr. Clark
susan.teacher # class variable
>> Mrs. Jones
Hopefully, you see how this behavior can lead to confusion. For this reason, it is important to keep variable names organized. If a variable is declared as a class variable, it should (usually) not be overridden. Instance variables can be defined in obvious places, like the __init__
method. It’s often good to come up with a naming convention for variables. For example, class methods should be verbs, class variables nouns, and instance variables nouns prefixed with an “_”.
6 – Using mutable objects as class variables
Related to the previous step, beware when using mutable objects as class variables. You might be surprised by the behavior.
Imagine we want a list of the student’s test scores. We might compose a class like this:
class Student:
teacher = 'Mrs. Jones'
test_scores = []
def __init__(self, name):
self.name = name
def add_score(self, score):
self.test_scores.append(score)
We’ve got a class variable to hold the scores, and we’ve got a class method for adding scores. Now let’s add some scores.
tom = Student('Tom')
susan = Student('Susan')
tom.add_score(90)
susan.add_score(100)
Can you guess what mistake we just made?
tom.test_scores
>> [90, 100]
Yep, test_scores
is a class variable, not an instance variable. Each instance is simply appending values to the class variable. What we really want is for each instance to hold its own list of test_scores
.
So a better class might look like this:
class Student:
teacher = 'Mrs. Jones'
def __init__(self, name):
self.name = name
self.test_scores = []
def add_score(self, score):
self.test_scores.append(score)
And now our problem is solved!
7 – Conclusion
Hopefully you’ve learned the difference between class and instance variables and what to expect from each. If I’m missing something in this guide or if you have any great examples of class and instance variable confusion, please comment below. I’d be happy to add them to this guide!