Python Class Variable: Shared State and Correct Usage
python class variable: Understand how Python class variables work, how they differ from instance variables, and when to use them without introducing subtle bugs.
python class variable requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.
In Python, a class variable is a variable defined directly inside a class body, outside any method. It belongs to the class itself, not to any single instance. All instances of the class share the same underlying value unless an instance creates its own copy. This behavior is central to many Python designs, but it also leads to confusion when mutable objects are involved.
Consider the simplest case:
class Counter: count = 0 # class variable def increment(self): Counter.count += 1
Here, count is a class variable. Every Counter instance sees the same count. Calling increment updates the shared value, and any instance can observe the change. This is useful for tracking totals across all instances, but it is not the same as an instance attribute.
Class Variables vs Instance Variables
An instance variable is assigned to self inside a method, typically __init__. It exists separately for each object. The same name can appear both as a class variable and as an instance variable without direct conflict, but the instance variable shadows the class variable when accessed through self.
class Example: value = "class" def __init__(self): self.value = "instance" e = Example() print(e.value) # instance print(Example.value) # class
Accessing e.value looks up the instance attribute first. If it exists, the class variable is ignored. If not, Python falls back to the class variable.
The distinction matters for both readability and correctness. A class variable represents state shared by the class, while an instance variable represents per-object state. Mixing them unintentionally creates bugs that are hard to trace.
| Access Path | What It Returns |
|---|---|
instance.attr | Instance attribute if present, else class |
Class.attr | Class attribute directly |
self.attr = x | Creates or overwrites an instance attribute |
How Class Variables Are Accessed and Modified
You can read a class variable through the class or through an instance. Writing to it is different. Assigning self.attr = value always creates an instance attribute, even if a class variable with the same name exists. To modify the class variable itself, you must assign through the class name or use type(self).
class Config: timeout = 30 c = Config() print(c.timeout) # 30 c.timeout = 60 # creates instance attribute print(c.timeout) # 60 print(Config.timeout) # 30 Config.timeout = 45 # updates class variable print(c.timeout) # still 60 because instance attr exists
This is a common source of confusion. If you intend to change the shared value, use Config.timeout = 45 or type(c).timeout = 45. The latter works even when the instance is of a subclass, but be careful with inheritance.
For methods that need to update a class variable, it is clearer to reference the class explicitly:
class Counter: count = 0 def increment(self): type(self).count += 1
Using type(self) makes the code work correctly with subclasses, because each subclass gets its own copy of the class variable if it is assigned through that subclass. The explicit Counter.count would always update the base class, which may not be what you want.
Mutable Class Variables and Shared State
A class variable that points to a mutable object—like a list, dict, or set—is shared across all instances. Mutating that object through one instance affects every other instance. This is often intentional, but it can also cause surprising behavior when you expect each instance to have its own copy.
class Team: members = [] # shared list def add_member(self, name): self.members.append(name) a = Team() b = Team() a.add_member("Alice") print(b.members) # ['Alice']
The list members is created once when the class is defined. Both a and b reference the same list. If you want each instance to have its own list, you must assign a new list in __init__:
class Team: def __init__(self): self.members = [] def add_member(self, name): self.members.append(name)
This is a classic pitfall. The problem is not the class variable itself, but the assumption that a mutable default belongs to each instance. A class variable is appropriate when the shared state is genuinely shared, such as a registry of all created instances or a configuration dictionary that should be global.
If you need a shared mutable structure but want to avoid accidental mutation, consider using an immutable type like a tuple, or expose only read-only access. For example, a class variable that holds a tuple of allowed options is safe because tuples cannot be changed in place.
Inheritance and Class Variable Behavior
Class variables are inherited by subclasses. When a subclass accesses a class variable, Python first looks in the subclass, then in the parent class. If a subclass assigns a value to the same name, it creates its own class variable that shadows the parent's.
class Base: kind = "base" class Child(Base): pass print(Child.kind) # base Child.kind = "child" print(Base.kind) # base print(Child.kind) # child
This behavior is useful for configuration that subclasses can override. However, it also means that a mutable class variable in the base class is shared by all subclasses unless a subclass reassigns it. If you modify a list that is defined in the base class through a subclass, the base class list is changed, and every other subclass sees that change.
class Base: items = [] class ChildA(Base): pass class ChildB(Base): pass ChildA.items.append("x") print(ChildB.items) # ['x']
To give each subclass its own independent list, you need to assign a new list in each subclass body, or use a factory method that creates a fresh list. The latter is often cleaner:
class Base: @classmethod def get_items(cls): return []
But that changes the semantics from a class variable to a method call. Decide based on whether the data is truly global to the class hierarchy or per-subclass.
When to Use Class Variables
Class variables are appropriate when the value is conceptually a property of the class, not of any particular instance. Common uses include:
- Constants that are shared across all instances, such as a default timeout or a version string.
- Counters or registries that track all instances of a class.
- Configuration values that subclasses can override.
- Cached values that are expensive to compute and identical for all instances.
For constants, consider using a class variable with an uppercase name, even though Python does not enforce immutability. For example:
class HttpStatus: OK = 200 NOT_FOUND = 404
This is a common pattern for grouping related constants. It avoids global variables and keeps the constants attached to the class.
Use an instance variable when the value should differ between objects. The rule of thumb is: if you would ever assign self.attr = ... inside __init__, that attribute should not be a class variable unless you intentionally want to share the initial value and then shadow it per instance.
Common Mistakes and How to Avoid Them
The most frequent mistake is using a mutable class variable as a default for instance attributes. The classic example is a list or dict defined in the class body, then modified through self. The fix is to assign a new mutable object in __init__.
Another mistake is assuming that assigning through self updates the class variable. It does not. If you need to update the class variable, use the class name or type(self).
A third mistake is forgetting that subclasses share the base class's mutable class variable. If you want per-subclass state, reassign the variable in each subclass or use a classmethod that returns a fresh object.
Finally, be careful when combining class variables with __slots__. If a class defines __slots__, instance attributes are limited to the listed names. Class variables are still allowed, but they do not conflict with slot names unless the slot name matches. This is an advanced scenario, but it can cause confusion if you expect a class variable to be accessible as an instance attribute.
Class Variables in Practice: A Registry Example
A common real-world use is a registry of instances. You can keep a class variable that holds a list of all created objects, and populate it in __init__.
class Registered: instances = [] def __init__(self, name): self.name = name self.instances.append(self)
Here, instances is a class variable. Every time a new Registered object is created, it is added to the shared list. This allows you to iterate over all instances later. The list is mutable, but that is intentional because the registry is meant to grow.
If you need to clear the registry, you can do Registered.instances.clear() or reassign Registered.instances = []. Reassigning creates a new list; any existing references to the old list will not see the new one. This is a subtle point: if another object holds a reference to the original list, it will not reflect the reassignment.
For a thread-safe registry, you would need locking, but that is beyond the scope of class variable semantics. The key point is that class variables are shared, and any mutation is visible to all holders of the same object.
Class Variables and Memory Efficiency
Class variables are stored once per class, not per instance. This can reduce memory usage when many instances share the same immutable value. For example, if a class has a constant PI = 3.14159, every instance does not need its own copy; they all reference the class variable.
However, if you assign an instance attribute with the same name, you create a separate copy for that instance, which uses more memory. In performance-sensitive code, avoid shadowing class variables with per-instance values unless necessary.
There is no runtime cost for reading a class variable through an instance; Python's attribute lookup checks the instance dictionary first, then the class. The lookup is fast, but it does involve a dictionary lookup on the class if the instance does not have the attribute. For most applications, this is negligible.
Final Technical Consideration: Using __set_name__ and Descriptors
When a class variable is assigned a descriptor object, such as a property or a custom descriptor, the descriptor's __set_name__ method is called automatically when the class is created. This is an advanced use of class variables that can control access to instance attributes.
class PositiveNumber: def __set_name__(self, owner, name): self.name = name def __get__(self, obj, objtype=None): if obj is None: return self return obj.__dict__.get(self.name) def __set__(self, obj, value): if value < 0: raise ValueError("must be positive") obj.__dict__[self.name] = value class Order: quantity = PositiveNumber()
Here, quantity is a class variable that is a descriptor. The descriptor intercepts attribute access on instances. This pattern allows you to add validation without writing __init__ boilerplate. It is a powerful use of class variables, but it requires understanding how descriptors work.
The key takeaway is that a class variable is not just a simple value; it can be any object, including callables and descriptors. The Python data model gives class variables a central role in attribute resolution, and understanding that role helps you write more predictable object-oriented code.