Back to Blog
Python

Python Class Variable vs Instance Variable

python class variable vs instance variable: Learn how Python class variables differ from instance variables, how attribute lookup works, and when shared state causes b...

class variablesinstance variablesattribute lookupshared statepython OOP
Diagram comparing a Python class variable shared across all instances with instance variables held separately by each object.

The distinction between python class variable vs instance variable determines how state is shared across objects of the same class. A class variable is defined directly in the class body and is shared by every instance, while an instance variable is assigned to self and exists independently for each object. Getting this distinction wrong leads to subtle bugs where one object's mutation silently changes the behavior of other objects.

How Python Stores Class and Instance Variables

When you define a class, names assigned in the class body become attributes on the class object itself:

class InventoryItem: category = "general" # class variable def __init__(self, name): self.name = name # instance variable

category lives on the InventoryItem class object. name lives on each individual instance. You can confirm this by inspecting the __dict__ of each:

item = InventoryItem("hammer") print(InventoryItem.__dict__["category"]) # "general" print(item.__dict__) # {"name": "hammer"}

The instance dictionary contains only name. The class dictionary contains category along with the methods. This storage difference is the root of all behavioral differences between the two.

Attribute Lookup Order

When you read item.category, Python does not immediately look in the instance dictionary. It follows a lookup chain: first the instance __dict__, then the class, then base classes in MRO order. Because category is not in the instance dictionary, the lookup falls through to the class and finds it there.

This explains why reading a class variable through an instance works, but assigning to it through an instance does not modify the class variable:

item = InventoryItem("hammer") item.category = "tool" # creates an instance attribute print(item.category) # "tool" print(InventoryItem.category) # "general"

The assignment item.category = "tool" creates a new entry in the instance dictionary, shadowing the class variable for that instance only. The class variable remains unchanged. This is a common source of confusion for developers new to the distinction.

Mutable Class Variables and Shared State

The most dangerous case is a mutable class variable. Because all instances share the same object, mutating it through one instance affects every other instance:

class Task: tags = [] # shared list def __init__(self, name): self.name = name def add_tag(self, tag): self.tags.append(tag) a = Task("build") b = Task("deploy") a.add_tag("backend") print(b.tags) # ["backend"]

a.add_tag("backend") appends to the list object stored on the class, not to a per-instance list. Both a and b see the same list because they both fall through to the class attribute. If the intent was per-task tags, this is a bug.

The fix is to initialize the mutable value in __init__:

class Task: def __init__(self, name): self.name = name self.tags = [] def add_tag(self, tag): self.tags.append(tag)

Now each instance gets its own list, and a.tags and b.tags are independent.

Class Variables as Defaults

A common pattern is to use a class variable as a default value that instances can override. This works cleanly with immutable values:

class Report: format = "pdf" def __init__(self, title, format=None): self.title = title if format is not None: self.format = format r1 = Report("q1") r2 = Report("q2", "csv") print(r1.format) # "pdf" print(r2.format) # "csv" print(Report.format) # "pdf"

r2.format is an instance attribute that shadows the class default. r1 falls through to the class default. This pattern is useful for configuration defaults, but it breaks when the default is mutable, as shown above.

Inheritance and Class Variable Shadowing

Subclasses inherit class variables from their parent, but assigning a class variable in a subclass creates a separate attribute on the subclass:

class Animal: sound = "..." class Dog(Animal): sound = "bark" class Cat(Animal): sound = "meow" print(Dog.sound) # "bark" print(Cat.sound) # "meow" print(Animal.sound) # "..."

Each subclass has its own sound in its own class dictionary. Mutating Dog.sound does not change Animal.sound or Cat.sound. However, if a subclass does not define its own value, it inherits the parent's class variable, and mutating it through the subclass affects the parent and all other subclasses that share it:

class Animal: registry = [] class Dog(Animal): pass Dog.registry.append("rex") print(Animal.registry) # ["rex"]

Because Dog has no registry of its own, the lookup falls through to Animal, and the mutation changes the shared list.

Performance and Memory Considerations

Class variables occupy memory once on the class object, regardless of how many instances exist. Instance variables occupy memory per instance. For a class instantiated thousands of times, storing a large default value as a class variable avoids duplicating it across every instance. However, the shared-state risk usually outweighs the memory savings unless the value is truly read-only.

There is also a small runtime cost to the attribute lookup chain. Reading an instance variable is a direct dictionary lookup on the instance. Reading a class variable through an instance requires the fallback lookup. In practice, this difference is negligible for typical application code, and optimizing it prematurely is rarely justified.

Choosing Between Class and Instance Variables

Use a class variable when the value is genuinely shared across all instances and should be the same for every object: constants, configuration defaults, counters, registries, or class-level metadata. Use an instance variable when the value describes the individual object: a name, an ID, a computed result, or any mutable collection that should be independent per instance.

A practical rule: if you would ever write self.something = ... in __init__, that value belongs on the instance. If the value is defined once and never reassigned per instance, it can live on the class. When in doubt, prefer instance variables for mutable state because they eliminate the shared-state hazard by construction.

python class variable vs instance variable: Practical Usage | RYUSLOG DEV