Introduction
If your Python class variables are behaving strangely, the problem is usually not Python itself. The problem is shared state that was meant to be shared, but got used like per-object data.
class declaration python is one of those topics that looks basic until it causes a bug you can’t spot quickly. A single misplaced attribute can affect defaults, counters, object state, and even inheritance behavior across an entire codebase.
Quick Answer
class declaration python refers to defining attributes on the class itself so every instance can share the same value. Class variables are best for shared defaults, counters, and constants, while instance variables are better for data that changes from object to object. Misusing class variables is a common source of Python bugs.
Definition
A class variable is an attribute defined on the class rather than inside an individual object, which means every instance can read the same value unless it is overridden by an instance attribute.
| Concept | Python class variables |
|---|---|
| Declaration Style | Defined directly in the class body as of August 2026 |
| Best Use Cases | Shared defaults, counters, constants, registries |
| Common Risk | Unexpected shared mutation across instances |
| Lookup Order | Instance first, then class, then parent classes as of August 2026 |
| Safer Access | Use the class name for shared values |
| Mutable Data Warning | Lists and dictionaries can create hard-to-track bugs |
Understanding class variables makes code easier to read and safer to maintain. It also helps when you need shared class data such as a default company name, an object counter, or a registry of created objects.
For the standard definition of Python itself, see Python. For object-oriented inheritance behavior, the first thing to understand is that class-level values are resolved differently from instance values.
A class variable is not “global” in the loose sense. It is scoped to the class, inherited by subclasses, and resolved through Python’s attribute lookup rules.
This guide breaks down the class in python syntax, shows a clear __init__ python example, explains how to access class variable python attributes correctly, and shows when python initialize class variable patterns help versus hurt.
Understanding Class Variables in Python
Class variables are attributes stored on the class object itself, not inside each instance. That means one shared value can be read by every object created from that class unless an object defines its own attribute with the same name.
This is why class variables are useful for values that should stay consistent across all objects. A company name, a default tax rate, a shared counter, or a configuration flag often belongs on the class because it describes the class as a whole rather than one specific object.
How shared class data works
When you create multiple objects from the same class, they do not each get a separate copy of every class variable. Instead, Python performs attribute lookup when you access the attribute, and if the instance does not have its own value, Python falls back to the class.
That behavior is efficient and clean, but it can also be misleading. A developer may think they updated one object when they actually changed a shared class-level value, which then affects every other object that reads from the class.
- Shared default means every instance sees the same starting value.
- Class-wide counter means one number tracks activity across all objects.
- Constant-style setting means the value should not vary per instance.
- Object-specific data means the value should live in an instance variable instead.
The key rule is simple: if the value can differ from object to object, it probably belongs in an instance variable. If it describes the class itself, a class variable is a reasonable fit.
For a deeper look at Python attribute behavior, the glossary definition for Inheritance helps explain why subclass lookups can also see class variables from parent classes.
Class Variables vs Instance Variables
Instance variables belong to one object, while class variables belong to the class definition. That is the core distinction, and it drives how Python stores, looks up, and updates data.
Most instance variables are created in __init__, which is why an __init__ python example is usually the easiest way to show per-object state. Class variables, by contrast, are usually declared at the top level of the class body.
Side-by-side comparison
| Class Variable | Shared by all instances unless overridden, declared in the class body |
|---|---|
| Instance Variable | Unique to one object, often created in __init__ |
Here is the practical difference: if you assign to an attribute through an instance, Python usually creates or updates that instance’s own attribute instead of changing the class variable. That surprises people because the code looks like a shared update, but the result is local to one object.
- Python checks the instance first.
- If the attribute is not found there, Python checks the class.
- If needed, Python checks base classes through the inheritance chain.
This means the same attribute name can behave differently depending on where it was assigned. A class can define role = "admin", but one instance can later define its own role and shadow the class value.
If you are deciding between the two, ask one question: does this value belong to one object or all objects? If it belongs to one object, make it an instance variable. If it belongs to the whole class, use a class variable.
How to Declare Class Variables
Class declaration python syntax is straightforward: put the variable directly inside the class body, outside any method. That is the cleanest and most readable way to declare shared state.
Placing class variables near the top of the class makes them easy to scan during code review. It also separates shared class data from method logic, which helps other developers understand what is truly global to the class.
Standard syntax
class Employee:
company_name = "ITU Online IT Training"
total_employees = 0
def __init__(self, name):
self.name = name
Employee.total_employees += 1
In that example, company_name and total_employees are class variables. Every instance can read them, and the counter can be updated in a controlled way when a new employee object is created.
Class variables can hold strings, numbers, booleans, lists, dictionaries, sets, or even custom objects. The type is not the issue; the issue is whether you want that value to be shared. Mutable values need extra care because changing the object changes it for every reference that points to the same shared object.
Pro Tip
Put class variables above methods and give them names that make their purpose obvious. If a variable is intended to be shared, make that intent visible in the class definition.
Subclasses also inherit class variables unless they override them. That is powerful for defaults, but it also means a simple declaration can influence behavior across a hierarchy of related classes.
For syntax that supports nested objects and class definitions, the official Python documentation remains the most reliable reference.
How Does Python Resolve Class Variable Access?
Python attribute lookup is the process Python uses to find a name on an object. For class variables, that process usually starts with the instance, then moves to the class, then walks up the parent classes.
That lookup order matters because reading and assigning are not the same thing. An instance can read a class variable without owning it, and later a local assignment can hide the class value without changing the class itself.
- Python checks whether the instance has its own attribute.
- If not, Python checks the class where the object was defined.
- If still not found, Python checks base classes in method resolution order.
- If the name does not exist anywhere, Python raises an
AttributeError.
Reading a class variable from the class and from an instance
class Employee:
company_name = "ITU Online IT Training"
employee = Employee()
print(Employee.company_name) # ITU Online IT Training
print(employee.company_name) # ITU Online IT Training
Both reads return the same value here because the instance does not have its own company_name. The class variable is shared, so the lookup lands on the class.
For readability, use the class name when the value is truly shared across all instances. That makes your intent obvious and reduces confusion during debugging.
The important detail is that reading through the instance is allowed, but updating through the instance can produce different behavior. That is where many class-variable bugs begin.
For broader attribute resolution concepts, the glossary term Lookup applies directly to how Python finds attributes on objects and classes.
How to Modify Class Variables Correctly
Modifying a class variable is safe when you do it on the class itself and understand the shared impact. The same update through an instance can create a separate instance attribute instead of changing the class-wide value.
That difference is subtle, but it is one of the most common sources of confusion in Python OOP. A developer sees a value change and assumes the class changed, when in reality only one object was updated.
Update the class directly when the value is shared
class Employee:
total_employees = 0
def __init__(self, name):
self.name = name
Employee.total_employees += 1
This pattern works because total_employees is supposed to count all instances. The class owns the counter, and each new object increments it in a controlled way.
The shadowing bug to avoid
class Employee:
company_name = "ITU Online IT Training"
employee = Employee()
employee.company_name = "Changed locally"
print(Employee.company_name) # ITU Online IT Training
print(employee.company_name) # Changed locally
In this example, the instance assignment does not update the class variable. It creates an instance attribute with the same name, which shadows the class value for that one object.
Warning
If you want all objects to see the change, update the class attribute on the class. If you want only one object to change, update the instance attribute intentionally and document that choice.
Use class-level mutation carefully. Shared state is useful for counters, caches, and registries, but it becomes hard to debug when the meaning of the variable is not obvious to the next developer reading the code.
What Are Practical Examples of Class Variables?
Practical examples make class variables much easier to understand because the pattern becomes concrete. The same idea shows up in counters, defaults, registries, and constants.
These examples also show where class variables fit well and where they do not. The goal is not to use them everywhere. The goal is to use them where shared state is the right design.
Counter example
class Ticket:
total_tickets = 0
def __init__(self, title):
self.title = title
Ticket.total_tickets += 1
Every time a new ticket object is created, the class counter increases. This is a classic class-variable use case because the count belongs to the class as a whole, not to one ticket.
Default configuration example
class ServerConfig:
environment = "production"
retry_limit = 3
These values work well as class variables if they are intended to be the default for all instances. If one object needs a different retry limit, set an instance attribute for that object instead.
Registry-style example
class Plugin:
registry = []
def __init__(self, name):
self.name = name
Plugin.registry.append(self)
This pattern is intentionally shared. The class keeps track of every created object in one place, which can be useful for plugin systems, reporting, or later lookup.
Constant-style example
class Employee:
company_name = "ITU Online IT Training"
A constant-style class variable is a good fit when every instance should report the same organization or default label. It is simple, readable, and easy to access from anywhere in the class.
In real systems, you will often see class variables used to define shared defaults in libraries, service objects, and configuration classes. The best examples are boring in the best possible way: they are clear, predictable, and hard to misuse.
For shared, class-scoped behavior in Python, the official Python data model documentation is the best source for deeper lookup rules and object behavior.
What Are the Common Pitfalls and Bugs?
Common pitfalls usually come from confusing class-wide data with object-specific data. That confusion is why a class variable can look correct in one place and wrong somewhere else.
The most classic bug is using a class variable for values that should differ per object. That causes one instance to accidentally influence another, which is especially painful in long-running applications or tests that reuse objects.
Mutable class variables are the biggest trap
Lists, dictionaries, and sets are mutable, so a change made by one instance is visible to all instances sharing that object. If you append to a class-level list, every object sees the new item.
class Team:
members = []
def __init__(self, name):
self.name = name
Team.members.append(name)
This can be intentional for a registry, but it is dangerous if you expected each object to own its own list. If the list is meant to be private to each object, create it in __init__ instead.
Shadowing hides the real source of truth
Another bug appears when an instance attribute masks a class variable of the same name. The object appears to have “changed the class value,” but it only changed its own local version.
Symptoms often include one object behaving differently from the rest, or a test failing because a value changed in one case but not in another. That usually means the code updated the wrong level.
- Shared mutation affects all objects at once.
- Shadowing creates a new instance attribute with the same name.
- Wrong storage location makes debugging slower and more confusing.
For diagnosing object-state issues, the glossary term Debugging is relevant because class-variable bugs often require careful inspection of where data is stored.
How Do Class Variables Work with Inheritance?
Inheritance changes class-variable behavior because subclasses can read, override, or mutate values from their parent classes. Python looks up the attribute through the class hierarchy if it is not found on the subclass itself.
That makes class variables useful for shared defaults across related classes. A base class can define a standard value, and a subclass can either reuse it or override it for specialized behavior.
Inherited read behavior
class Vehicle:
wheels = 4
class Truck(Vehicle):
pass
Truck.wheels returns 4 because the subclass inherits the class variable from Vehicle. The subclass does not need to redefine it unless the default changes.
Subclass override behavior
class Vehicle:
wheels = 4
class Motorcycle(Vehicle):
wheels = 2
Here the subclass has its own version of wheels. The parent class remains unchanged, and the subclass gets a separate class-level value.
The tricky part is mutation. If the shared value is a list or dictionary, a subclass may still reference the same object unless it overrides that object with a new one. That is one reason mutable class variables deserve extra caution.
Inheritance-based class variables are useful when you want a shared default with controlled override points. They are less useful when each subclass should manage completely separate behavior, because that can make the hierarchy harder to reason about.
For design guidance around object hierarchy, Inheritance is the right conceptual anchor for how base-class attributes flow downward.
What Should You Know About Class Variables with Mutable Objects?
Mutable class variables require special care because one change can affect every object that shares the same reference. Lists, dictionaries, and sets are the most common troublemakers.
That does not mean you can never use them. It means you need to be deliberate about whether the shared mutation is part of the design or an accidental side effect.
Shared list example
class Project:
tags = []
def add_tag(self, tag):
Project.tags.append(tag)
If every object should contribute to one shared list of tags, this pattern is acceptable. If each project needs its own tags, then the list must be created on the instance instead.
Safer per-instance alternative
class Project:
def __init__(self):
self.tags = []
Now every object gets its own independent list. One object can add, remove, or replace tags without affecting any other object.
Key Takeaway
Use shared mutable class data only when the sharing is intentional. If each object should own its own collection, initialize it inside __init__ instead of the class body.
Shared mutable state is sometimes useful for caches, registries, and coordination objects. The key is to document the behavior clearly so no one assumes the data is isolated when it is not.
For practical standards around clean Python object design and container behavior, the official Python docs are more reliable than scattered examples online.
How Do You Debug and Test Class Variable Behavior?
Testing class variable behavior is the fastest way to catch shadowing and accidental shared mutation. A few focused assertions can save hours of guessing later.
During debugging, inspect both the instance and the class. That tells you where Python is actually storing the attribute and whether the value has been shadowed locally.
Check storage location explicitly
class Employee:
company_name = "ITU Online IT Training"
employee = Employee()
print(employee.__dict__)
print(Employee.__dict__.get("company_name"))
If the attribute appears in employee.__dict__, it belongs to the instance. If it only appears in the class dictionary, it is still a class variable.
Useful assertions for tests
- Verify two objects see the same shared class value when they should.
- Verify one object’s override does not change the class value.
- Verify mutable class data changes only when intentional.
- Verify subclasses inherit or override behavior correctly.
For example, a test can assert that a class counter increases when a new instance is created, while a per-object list remains independent. That combination catches both accidental sharing and accidental duplication.
Interactive inspection in the Python shell is also useful. Print the object, print the class, inspect __dict__, and compare the results before and after assignment. The pattern is simple, but it exposes the exact moment an instance starts shadowing a class variable.
What Are the Best Practices for Using Class Variables?
Best practices for class variables are mostly about restraint. Use them when the value truly belongs to the class, and keep them obvious, intentional, and easy to reason about.
The safest rule is this: if the value feels like shared configuration, a class variable may be right. If it feels like object state, it probably belongs in the instance.
- Use class variables for shared defaults such as a company name, version label, or counter.
- Use the class name for updates when the intention is to change shared state.
- Avoid mutable class variables unless the shared mutation is explicitly part of the design.
- Keep class variables near the top of the class so they are easy to spot.
- Reevaluate the design if the data starts acting like per-object state.
A well-designed class makes its shared state obvious. A poorly designed class hides state changes behind instance assignments, shared lists, or inheritance chains that nobody expects.
That is why class variables should make code simpler, not cleverer. If a class variable increases confusion, the design is probably wrong for the problem you are solving.
For style and maintenance questions, the official Python documentation is the most practical source because it reflects the language’s real lookup and object rules.
Conclusion
Class variables are powerful when the value belongs to the class and should be shared by every instance. They are a poor fit for object-specific data, especially when the value needs to change independently from object to object.
The biggest mistakes come from confusing reading, assigning, and mutating. Reading a class variable is usually safe from both the class and the instance. Assigning through an instance can shadow the class value. Mutating a shared object can change it for every instance at once.
Use class variables for counters, defaults, registries, and true class-wide settings. Use instance variables for data that should stay isolated. If you follow that rule, your code becomes easier to test, easier to debug, and much less likely to produce hidden shared-state bugs.
Key Takeaway
Class variables work best for shared, class-wide data. Use the class name for shared access, keep mutable class data intentional, and move per-object values into __init__ when each instance needs its own state.
Apply these patterns in counters, default settings, shared configuration, and registries. Then test subclass behavior and mutable updates carefully so shared state stays predictable instead of surprising.
Python is a trademark of the Python Software Foundation.

