Fun with Learning Technology
LearnCoursesQuestionsTracksToolsNewsExplorePractice
Fun with Learning Technology

A new problem, explained clearly, every day.

Subscribe
Learn
  • Lessons
  • Topics
  • News
  • Tools
  • Courses
  • Career tracks
  • Everything
Site
  • About
  • Contact
  • Support
  • Privacy
  • Terms
Get the daily one

One email per new problem. No spam.

Request a tutorial

Requests shape what gets made next.

© 2026 Fun with Learning TechnologyRSS
Home›Courses›Python›Instance vs Class Variables

Object-Oriented Programming

Instance vs Class Variables

Instance variables hold unique data specific to a single object, while class variables store data shared across every instance of that class. Understanding this distinction is fundamental to managing memory and defining the behavior of your objects. Use instance variables for state that changes per object and class variables for shared configuration or constants.

The Anatomy of Instance Variables

Instance variables are defined within the __init__ method using the 'self' keyword. When you create an object, Python allocates a unique namespace for that instance, allowing it to store its own distinct values for those variables. This ensures that when you modify an instance variable on one object, it does not affect any other object created from the same class. The 'self' prefix essentially acts as a pointer, binding the data to the specific memory address of that individual instance. Because every object carries its own data set, instance variables are the primary mechanism for maintaining the unique internal state of your objects. Without them, it would be impossible to represent distinct items like different user profiles or unique bank account balances, as each entity would overwrite the data of the others upon modification.

class User:
    def __init__(self, username):
        # 'self.username' is an instance variable
        self.username = username

user1 = User('Alice')
user2 = User('Bob')
# Each object maintains its own unique state
print(user1.username)  # Output: Alice
print(user2.username)  # Output: Bob

Defining Class Variables

Class variables are defined directly inside the class body, outside of any methods. Unlike instance variables, these are tied to the class object itself rather than individual instances. When you define a variable at this scope, it becomes a shared attribute that all instances of the class can access. This is incredibly efficient when you have a piece of data that should be consistent for every object created from that class. Since the variable is stored in one location, memory is conserved because you are not duplicating the same information across thousands of objects. If you find yourself hardcoding the same configuration values inside multiple instance initializers, moving that data to a class variable is the standard approach to reduce redundancy and ensure global consistency across your object instances.

class Server:
    # 'connection_limit' is a class variable shared by all instances
    connection_limit = 100

    def __init__(self, host):
        self.host = host

s1 = Server('192.168.1.1')
s2 = Server('192.168.1.2')
# Both access the shared class variable
print(s1.connection_limit)  # Output: 100
print(s2.connection_limit)  # Output: 100

Understanding the Lookup Mechanism

Python's attribute resolution mechanism is designed to be intuitive but requires careful attention. When you attempt to access an attribute on an instance, Python first looks for it within the instance's own dictionary. If the name is not found there, Python moves up to the class dictionary to check for the attribute. This inheritance-like lookup is why class variables appear to be available on instances. However, this lookup is read-only when accessed through an instance. If you try to assign a value to an attribute that shares the name of a class variable using the instance reference, Python will create a new instance variable that shadows the class variable. The original class variable remains unchanged, and only that specific instance will now have its own unique value, effectively masking the class-wide default for that single object.

class Configuration:
    mode = 'production'

app = Configuration()
# Accessing class variable via instance
print(app.mode)  # Output: production

# Creating an instance-specific override
app.mode = 'development'
print(app.mode)  # Output: development
# The class itself remains unchanged
print(Configuration.mode)  # Output: production

The Hazards of Mutable Class Variables

A common trap when working with class variables is using mutable types like lists or dictionaries. Because class variables are shared across all instances, any modification to a mutable object stored as a class variable reflects across all instances simultaneously. If one object appends a value to a list stored in a class variable, that value becomes visible to every other object. This behavior can lead to subtle, difficult-to-track bugs where state 'leaks' between unrelated objects. To avoid this, always initialize mutable data structures inside the __init__ method as instance variables unless the intent is explicitly to maintain a shared log or registry across all instances of the class. Recognizing this distinction is vital for writing robust, predictable code that behaves reliably as your program scales in complexity and size.

class TaskRegistry:
    # DON'T do this if you want unique lists per instance
    tasks = []

worker1 = TaskRegistry()
worker2 = TaskRegistry()
worker1.tasks.append('Fix Bug')

# Both see the change because they share the same list reference
print(worker2.tasks)  # Output: ['Fix Bug']

Best Practices for Implementation

To maintain clean code, apply a simple rule: use instance variables for state, and class variables for constants or configuration. When you need to define a class variable, name it clearly to indicate it belongs to the class scope, often using uppercase if it represents a constant. If you find yourself needing to modify a class variable, do so via the class name itself rather than through an instance. This makes your intent explicit to other developers and avoids the accidental shadowing mentioned earlier. By keeping the modification logic focused on the class level, you maintain clear boundaries between global class data and individual instance data. Consistently following these patterns ensures that your object-oriented designs remain maintainable, scalable, and free from the confusion caused by mixed-scope attribute modifications during the execution of your application's logic.

class DatabaseConnection:
    TIMEOUT = 30  # Conventionally capitalized constant

    def __init__(self, db_name):
        self.db_name = db_name

# Modifying the class variable correctly
DatabaseConnection.TIMEOUT = 60
print(DatabaseConnection.TIMEOUT)  # Output: 60

Key points

  • Instance variables are defined inside the __init__ method using the self keyword.
  • Class variables are defined at the class level and are shared among all instances.
  • Accessing an attribute follows a lookup sequence starting from the instance and moving to the class.
  • Assigning to an instance variable name that matches a class variable will shadow the class variable.
  • Mutable objects in class variables are shared, which can lead to unexpected state leakage between instances.
  • Use instance variables to maintain the unique state of individual objects.
  • Class variables are best suited for constants or data shared across all instances of a class.
  • Always modify class variables through the class name to maintain code clarity and prevent shadowing errors.

Common mistakes

  • Mistake: Modifying a mutable class variable through an instance. Why it's wrong: It changes the shared value for all instances. Fix: Use instance variables for data unique to the object.
  • Mistake: Thinking class variables are constants. Why it's wrong: They are just shared attributes that can be updated at any time. Fix: Use conventions like ALL_CAPS for constants, but remember they aren't protected.
  • Mistake: Defining every variable in the class body. Why it's wrong: This forces data to be shared across every instance even when it should be unique. Fix: Initialize instance-specific data in the __init__ method.
  • Mistake: Accessing instance variables using the class name. Why it's wrong: Instance variables belong to the object, not the class, so they don't exist until the object is created. Fix: Access instance variables via the 'self' reference.
  • Mistake: Confusion about attribute lookup order. Why it's wrong: Python looks for the attribute on the instance first, then the class. Fix: Understand that if you assign a value to an instance with the same name as a class variable, you shadow the class variable for that instance only.

Interview questions

What is the fundamental difference between an instance variable and a class variable in Python?

An instance variable is specific to a single object, defined inside the __init__ method using 'self', meaning every instance has its own unique copy with its own value. In contrast, a class variable is defined directly within the class body, outside of any methods, and is shared by every instance of that class. If you change a class variable, it updates for all instances simultaneously because they all reference the same memory location, whereas changing an instance variable only affects that specific object.

How do you define and access a class variable in Python code?

To define a class variable, you place the assignment directly under the class header but outside of any methods, such as 'class Car: wheels = 4'. To access it, you can use the class name itself, like 'Car.wheels', which is the preferred and safest approach. While you can technically access class variables through an instance using 'my_car.wheels', this can lead to confusion if you accidentally create an instance variable with the same name, which would then shadow the class variable for that specific object.

Can you explain the potential pitfalls of modifying a class variable through an instance?

If you try to modify a class variable using an instance, such as 'instance.variable = value', Python does not actually update the class variable. Instead, it creates a new instance variable on that specific object with that same name, effectively masking the class variable from that point forward. This can lead to bugs where different instances appear to have different values for what should be a shared global constant, making the state of your application extremely difficult to debug and track.

When should you choose a class variable over an instance variable in your Python application?

You should choose a class variable when the data is meant to be shared across all instances, such as a counter for the number of objects created, a default configuration setting, or a constant that defines behavior for every object of that type. Conversely, use instance variables for data that is unique to each object, such as a user's name, their specific ID, or dynamic state information. Storing unique data in a class variable would lead to logical errors where objects overwrite each other's data.

Compare the approach of using a class variable for instance counting versus using a separate global counter.

Using a class variable for instance counting, like 'self.__class__.counter += 1', is superior to a global counter because it encapsulates the data within the class scope, preventing name collisions and keeping the logic organized. A global variable is accessible from anywhere in your module, which violates encapsulation principles. By tying the counter to the class, you maintain a clean interface and ensure that the state related to the class lifecycle is properly bundled within the class definition itself, making the code much more maintainable.

How does Python's method resolution order and attribute lookup behave when both an instance variable and a class variable share the same name?

When you attempt to access an attribute on an instance, Python first performs a lookup in the instance's own __dict__ dictionary. If the name is found there, it returns the instance variable value immediately. If the name is not found, Python then proceeds to check the class's dictionary, searching for the attribute at the class level. This hierarchical lookup is exactly why an instance variable can effectively hide or shadow a class variable; the instance lookup succeeds first, stopping the search before it ever reaches the shared class-level definition.

All Python interview questions →

Check yourself

1. Given a class 'Data' with a class variable 'count = 0', if you increment it using 'self.count += 1' inside an instance method, what happens?

  • A.It increments the class variable for all instances globally.
  • B.It creates a new instance variable 'count' for that specific instance, shadowing the class variable.
  • C.It raises an AttributeError because class variables cannot be accessed via self.
  • D.It modifies the class variable only if the instance has no other attributes.
Show answer

B. It creates a new instance variable 'count' for that specific instance, shadowing the class variable.
Option 2 is correct because the assignment creates a local instance attribute. Option 1 is wrong because assigning to 'self.count' does not update the class attribute. Option 3 is wrong because self can access class attributes. Option 4 is incorrect because attribute lookup is independent of other attributes.

2. What is the primary difference between how Python resolves attributes for 'self.var' and 'ClassName.var'?

  • A.self.var always checks the class first, then the instance.
  • B.ClassName.var only exists if an instance of the class has been created.
  • C.self.var checks the instance scope first, while ClassName.var checks the class scope directly.
  • D.They are identical and interchangeable in all Python versions.
Show answer

C. self.var checks the instance scope first, while ClassName.var checks the class scope directly.
Option 3 correctly describes the resolution order. Option 1 is wrong because instance lookup happens before class lookup. Option 2 is false as class variables are defined on the class itself. Option 4 is false as the scopes are distinct.

3. If a class has a list as a class variable, what is the risk of modifying it via an instance?

  • A.The modification only affects the current instance.
  • B.The list is copied to the instance scope automatically.
  • C.All instances of the class will see the modified list since they share the same object reference.
  • D.The code will throw a TypeError.
Show answer

C. All instances of the class will see the modified list since they share the same object reference.
Option 3 is correct because mutable objects like lists are shared. Option 1 is wrong because the mutation is in-place on the shared object. Option 2 is wrong because Python does not auto-copy. Option 4 is wrong because modifying an existing list is a valid operation.

4. Why should you typically initialize variables in the __init__ method?

  • A.To ensure they are treated as class variables.
  • B.To ensure they are unique to every instance created.
  • C.Because Python variables cannot be defined outside of methods.
  • D.To make the variables private.
Show answer

B. To ensure they are unique to every instance created.
Option 2 is correct because __init__ runs per instance creation. Option 1 is wrong because __init__ defines instance variables. Option 3 is wrong as class body definitions are legal. Option 4 is wrong because __init__ does not control visibility.

5. When is a variable defined in the class body accessible?

  • A.Only after an instance of the class has been instantiated.
  • B.Only within instance methods using self.
  • C.As soon as the class definition is executed, even without an instance.
  • D.Only when the variable is explicitly declared as global.
Show answer

C. As soon as the class definition is executed, even without an instance.
Option 3 is correct because class variables are defined when the class is created in memory. Option 1 is wrong because the class exists independently of instances. Option 2 is wrong because they are accessible via the class name. Option 4 is wrong as 'global' has no impact on class attributes.

Take the full Python quiz →

← PreviousThe __init__ ConstructorNext →Instance Methods

Python

78 lessons, free to read.

All lessons →

Track your progress

Sign in to mark lessons done, score quizzes and keep notes.

Open in the app