Python Class Variables in Python: Declaration, Usage, and Practical Examples
If a value should be the same for every object in a Python class, a class level variable python pattern is usually the right tool. It keeps shared data in one place, reduces duplication, and makes object behavior easier to reason about.
Many developers run into bugs when they treat shared data like it belongs to each object. That is where understanding class variables and instance variables matters. This guide shows how to declare them, how to access class variables Python objects use in practice, what happens when you modify them, and where the common traps are.
You will also see practical examples for counters and default configuration, plus debugging and testing techniques that help prevent shared-state surprises. The goal is simple: write object-oriented Python that is predictable, maintainable, and easy to scan when you come back to it later.
Understanding Python Class Variables
A class variable is an attribute stored on the class itself, not inside each object. Every instance can read that value, and if the class variable changes, the new value is visible to all instances unless an instance has its own attribute with the same name.
That distinction is the core of the class level variable python concept. If the value belongs to the whole type of object, use a class variable. If the value belongs only to one object, use an instance variable inside __init__.
Here is the practical reason this matters: shared data reduces repetition. You do not want every Employee object to store the same company name, or every Configuration object to duplicate the same default settings when one shared value will do.
Shared state is useful only when the value truly belongs to the class. If each object can change the value independently, it is probably an instance variable instead.
That rule sounds obvious, but it prevents a lot of bugs. A class variable is great for defaults, counters, flags, registries, and constants. It is a poor choice for personal preferences, names, salaries, or anything that varies from object to object.
Note
When you read a class variable through an instance, Python first checks the instance, then the class, then base classes. That lookup behavior explains most of the confusing cases people hit with shared attributes.
How to Declare Class Variables in Python
Class variables are usually declared directly in the class body, outside of methods. That makes them part of the class definition itself and clearly separates shared data from per-object data.
The syntax is straightforward. You assign a value at class scope, usually near the top of the class so readers can see the shared state immediately.
class Employee:
company_name = "ITU Online"
total_employees = 0
def __init__(self, name):
self.name = name
Employee.total_employees += 1
In this example, company_name and total_employees are class variables. Every object can read them, but they are stored once for the class rather than once per instance.
This is also where class-level constants and reusable defaults fit naturally. If a value should not be different across instances, define it once in the class declaration. That includes feature flags, version labels, default limits, or shared configuration values.
One practical point: class variables live in class scope, but they are not magic. They follow normal Python name lookup rules. If you define a variable in the class body, methods can reference it through the class name or through self when the lookup resolves to the class attribute.
- Use class variables for shared counters, constants, and defaults.
- Use instance variables for object-specific state inside
__init__. - Keep class declarations readable by grouping shared values near the top of the class.
For official background on Python object model behavior, the Python documentation is the best reference point, and it is worth keeping nearby when you work through lookup rules and attribute resolution: Python Documentation.
Accessing Class Variables Through the Class and Instances
You can read a class variable in two common ways: through the class name or through an instance. Both work, but they are not equally clear in every situation.
Using the class name is the most explicit option. It tells the reader immediately that the value belongs to the class, not the object.
class Employee:
company_name = "ITU Online"
employee = Employee("Ava")
print(Employee.company_name)
You can also access the same value through the instance:
print(employee.company_name)
That works because Python checks the instance first, then falls back to the class if the attribute is not found on the object itself. This is why accessing class variables Python developers often do through instances can be convenient, but it can also hide where the value really lives.
For readability, class-name access is usually better when you are dealing with shared state, shared defaults, or class-level constants. Instance access is fine when you are intentionally relying on inheritance or attribute lookup behavior, but it can be misleading if you are trying to show ownership.
| Access method | Why it helps |
Employee.company_name |
Clear, explicit, and obviously class-level |
employee.company_name |
Convenient, but may blur whether the value is shared or local |
If you want a practical rule, use the class name when documenting shared values in production code. It is easier to scan, easier to debug, and easier for teammates to understand six months later.
Modifying Class Variables and the Impact on Instances
Changing a class variable through the class updates the shared value for every instance that does not override it. That is the behavior people usually want when they are tracking global counts or updating shared settings.
class Employee:
company_name = "ITU Online"
e1 = Employee()
e2 = Employee()
Employee.company_name = "ITU Online Training"
print(e1.company_name)
print(e2.company_name)
Both instances now reflect the updated class value, because neither object has its own company_name attribute.
The tricky part is assignment through an instance. If you write e1.company_name = "Something else", Python creates or updates an attribute on that instance, not on the class. That means e1 now has its own version of the name, while e2 still sees the class value.
e1.company_name = "Local Override"
print(e1.company_name)
print(e2.company_name)
print(Employee.company_name)
This shadowing behavior is a common source of confusion. A developer thinks they changed the shared value, but they only changed one object. In debugging sessions, that mistake often looks like random inconsistency.
Warning
Assigning to an attribute through an instance does not necessarily modify the class variable. It may create a new instance attribute with the same name and hide the shared value.
To avoid confusion, make a habit of updating shared state through the class name unless you intentionally want an override on one object. That pattern is easier to review and much easier to maintain.
Class Variables vs Instance Variables
Instance variables store data that belongs to one specific object. They are usually created in __init__ and live inside the instance’s attribute dictionary. By contrast, class variables belong to the class and are shared across all instances.
The best way to think about it is ownership. If the value describes the object itself, use an instance variable. If the value describes the category of objects, use a class variable.
Here is a simple comparison:
| Class variable | Instance variable |
| Shared by all objects | Unique to each object |
| Defined in the class body | Usually defined in __init__ |
| Good for defaults and counters | Good for names, salaries, preferences, and object-specific state |
| Changing it can affect many instances | Changing it affects only one object |
For example, an employee’s name and salary are instance variables. A company-wide policy, default department, or shared employee count is better as a class variable. The same logic applies to user preferences, shopping cart contents, or device identifiers: if it varies per object, keep it local.
These two variable types often work together in the same class. A well-designed class usually has a few class variables for shared behavior and several instance variables for the object’s own state.
For a broader perspective on object-oriented design and attribute behavior, the official Python docs remain the most accurate reference: Python Classes Tutorial.
Practical Example: Tracking Employee Counts
A shared counter is one of the cleanest uses of a class variable. If you need to know how many Employee objects have been created, a class-level counter is a natural fit.
Here is a simple implementation:
class Employee:
total_employees = 0
def __init__(self, name):
self.name = name
Employee.total_employees += 1
e1 = Employee("Ava")
e2 = Employee("Noah")
e3 = Employee("Mia")
print(Employee.total_employees)
Every time an instance is created, the counter increases. This is useful for tracking registrations, active sessions, issued devices, or any process where you need a basic count of created objects.
The reason this works well is that the count is not a property of one employee. It is a property of the whole class. Storing it on the class keeps the logic simple and avoids passing shared counters around between objects or helper functions.
There are limits, though. If an object is deleted, the counter does not automatically decrease unless you write logic for it. And if your application restarts, the counter resets unless you persist it somewhere like a database, cache, or log analysis pipeline.
Use class counters for lightweight tracking, not for durable records. If the number must survive restarts or support auditing, store it outside the Python process.
That distinction matters in real applications. A process-local count is fine for diagnostics or temporary reporting. A business-critical count should be managed with a persistent data store and proper transaction logic.
Practical Example: Default Configuration Settings
Class variables are also a solid choice for reusable defaults. A configuration object often starts with a shared set of settings and then overrides only the values that differ for a specific environment or instance.
class Configuration:
default_config = {
"timeout": 30,
"retries": 3,
"debug": False
}
def __init__(self, custom_config=None):
self.config = Configuration.default_config.copy()
if custom_config:
self.config.update(custom_config)
app_config = Configuration({"debug": True})
print(app_config.config)
This pattern keeps default values in one place. If you need to change the standard timeout or retry count, you update the class variable once and every new configuration object can inherit the new baseline.
The copy() call is important. Without it, a mutable dictionary stored at the class level could be changed by one instance and accidentally affect all other instances. That is one of the most common class variable mistakes in Python.
Use this pattern for application settings, environment-specific defaults, feature flags, request templates, or any place where a shared baseline makes sense. Then let each instance override only what it needs.
- Good use: default API timeouts shared across service objects.
- Good use: feature flags that should start with the same default value.
- Good use: environment settings that are copied and then customized.
- Bad use: storing per-user preferences in a shared dictionary.
For configuration-heavy projects, official vendor documentation is often the best source of truth. If your settings map to a cloud or platform service, consult the vendor’s own docs rather than relying on assumptions.
Common Pitfalls When Using Class Variables
The biggest mistake is using mutable class variables without understanding how shared state works. Lists, dictionaries, and sets are especially risky because one instance can change the shared object for every other instance.
class Team:
members = []
t1 = Team()
t2 = Team()
t1.members.append("Ava")
print(t2.members)
In this case, both objects see the same list. That is usually not what the author intended.
Another common issue is confusing reassignment with mutation. Reassigning a new object changes the reference, while mutating a shared object changes the contents of the same object. Those are not the same thing, and the difference matters a lot when the value is shared.
You also need to watch for accidental shadowing. If an instance gets an attribute with the same name as the class variable, the instance version hides the class value. That can make debugging frustrating because the code appears to be reading one thing while actually using another.
Pro Tip
If you must use mutable class-level data, document it clearly and test the change path. Better yet, copy the value inside the instance before modifying it.
Shared-state bugs are often hard to spot because the failure appears far away from the cause. One method mutates a class-level list, and another method later reads the changed list without realizing where the update came from. Good naming, limited mutability, and focused tests go a long way.
For defensive coding guidance, the broader Python ecosystem also emphasizes explicit state management and clear attribute ownership. That principle aligns with the language’s own object model and helps reduce hard-to-trace behavior.
Best Practices for Working With Class Variables
Use class variables only when the data truly belongs to the class. That one rule eliminates most misuse. If the value should be shared, stable, and easy to understand across instances, class-level storage is appropriate.
Prefer immutable values whenever possible. Strings, numbers, and tuples are safer than lists and dictionaries because they cannot be changed in place. When you do need mutable defaults, copy them before modifying them inside an instance.
Access shared values through the class name when clarity matters. This makes your intent obvious in code reviews and reduces the risk of accidentally creating an instance attribute with the same name.
Document class variables just like you would document methods. Future readers need to know whether a value is shared, whether it should be changed, and whether subclasses are expected to override it.
- Keep shared state small and easy to understand.
- Use immutable values for constants whenever possible.
- Copy mutable defaults before changing them in instances.
- Prefer class-name access for explicit shared state.
- Test shadowing behavior if subclasses or instances may override values.
The Python core documentation remains the best reference for class and attribute mechanics: Python Data Model. If you are writing code for a team, pair that with your own style rules so shared state is handled consistently.
Advanced Uses of Class Variables
Class variables can do more than store defaults. They can also support registries, caches, feature toggles, and metadata that needs to be shared across objects of the same type.
A registry is a common pattern. You might store all created objects in a class-level list or dictionary so the class can find, inspect, or manage its own instances. That can be useful in plugin systems, object lookups, or lightweight in-memory coordination.
class User:
active_users = []
def __init__(self, username):
self.username = username
User.active_users.append(self)
Class variables also work well for behavior flags. For example, a class-level debug_enabled flag can turn on extra logging for every instance of the class at once. That is handy in testing or troubleshooting, but it should be used carefully so one change does not unexpectedly affect unrelated logic.
Inheritance adds another layer. Subclasses can override class variables to customize defaults without changing the parent class. That is useful when a base class defines shared behavior, but a child class needs a different threshold, label, or policy.
For developers working on larger systems, this is where class variables become powerful and dangerous at the same time. They can support application-wide state, but that state should remain small and intentional. If the shared state starts acting like a database, it probably belongs somewhere else.
When subclass behavior matters, the Python docs on inheritance and attribute lookup are worth reviewing carefully: Python Inheritance Documentation.
Debugging and Testing Class Variables
When class variables behave unexpectedly, the first step is to inspect where the value is stored. Printing both the class and the instance often reveals whether you are looking at shared state or a shadowed instance attribute.
print(Employee.__dict__)
print(e1.__dict__)
__dict__ shows the attribute storage for the class or instance. If a name appears in the instance dictionary, that instance has its own copy. If it only appears in the class dictionary, the value is being inherited through lookup.
This is especially helpful when debugging the class level variable python pattern in a team codebase. A variable may look shared in one code path and local in another, depending on how it was assigned.
Tests should also reset class variables between runs when shared state could leak from one test to another. That is a common problem in unit test suites, especially when class variables are mutated during setup or during the test itself.
- Inspect the class and instance dictionaries.
- Check whether the value was assigned on the class or on the object.
- Reset mutable class variables in test setup or teardown.
- Assert the expected behavior for both shared and overridden values.
Consistent naming helps too. If the team knows that class variables are always accessed through the class name in application code, debugging becomes much simpler. You can tell at a glance whether the code is using shared state or object-specific data.
Key Takeaway
If a test passes only when run alone, shared class state may be leaking across tests. Reset class variables early and often.
Conclusion
Python class variables are the right choice when data belongs to the class as a whole rather than to one object. They are useful for counters, defaults, shared flags, registries, and other values that should be consistent across instances.
The key difference from instance variables is ownership. Class variables live on the class and can be shared. Instance variables live on each object and can vary independently. Once you understand that distinction, the behavior of access, shadowing, and mutation becomes much easier to predict.
The practical examples in this guide show how to track employee counts and manage default configuration safely. Those patterns are common, easy to reuse, and a good fit for many object-oriented Python programs.
Use class variables carefully, keep mutable shared state under control, and access shared values through the class when clarity matters. If you follow those habits, the class level variable python pattern becomes a useful part of your design instead of a debugging headache.
If you want more structured Python training from ITU Online IT Training, use this article as a reference while you practice with real classes, real objects, and real edge cases.
Python is a registered trademark of the Python Software Foundation.
