Understanding class vs. instance variables in Python 3

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

First, a quick review if you're new to object oriented programming. A class is 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 take away 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

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

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

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

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: instances 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 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

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

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!