Sitemap

Class and instance attributes in Python

4 min readDec 3, 2025

--

Understanding attributes in Python can be quite confusing when you’re navigating the differences between class and instance variables. By the end of this guide, you’ll have a comprehensive understanding that you can explain confidently without the need to search on Google or ask generative AI.

Whats a class attribute?

A class attribute in python is a variable that is owned by the class itself, rather than by any specific instance (object) of that class. This means all instances of a class share the same class attributes.

Example:

class A:
a = "I am a class attribute!"

x = A()
y = A()
x.a

The output of the above program would be ‘I am a class attribute!’. The same applies if you called

y.a

or even

A.a

As you can see, since it’as a class attribute, all instances of the class share the same value as long as you don’t individually modify it. You could also direclty call the class itself and modify the attribute’s value for all instances:

A.a = "This is changing the class attribute 'a'!"
A.a

This way, the output for “A.a” and every instance calling the a attribute would be “This is changing the class attribute ‘a’!”

Whats an instance attribute?

In Python, an instance attribute is essentially the opposite to a class attribute. It belongs specifically to an individual object of a class, rather than the class itself. Therefore, it can only be acces through its owner instance of the class, not by the class itself. It’s also independent of other instances of the same class.

class Dog:
def __init__(self, name, age):
self.name = name # 'name' is an instance attribute
self.age = age # 'age' is an instance attribute

# Create two instances of the Dog class
dog1 = Dog("Buddy", 5)
dog2 = Dog("Lucy", 3)

# Access and modify instance attributes
print(f"{dog1.name} is {dog1.age} years old.") # Output: Buddy is 5 years old.
print(f"{dog2.name} is {dog2.age} years old.") # Output: Lucy is 3 years old.

dog1.age = 6
print(f"{dog1.name} is now {dog1.age} years old.") # Output: Buddy is now 6 years old.
print(f"{dog2.name} is still {dog2.age} years old.") # Output: Lucy is still 3 years old.

You can also add instance attributes outside of the __init__ method

dog1.new_attribute = "added later"
print(dog1.new_attribute) #Output: added_later

What are the ways of creating it and whats the most pythonic one

Get Anthonybemol’s stories in your inbox

Join Medium for free to get updates from this writer.

As we mentioned before, you can create instance attributes by assigning them in the __init__ constructor, which is the most concise and most Pythonic method. You can also create them directly after creating a new instance of the class as we also mentioned before. Other methods include using setter methods, like this:

class Dog:
def __init__(self, name, age):
self.name = name # 'name' is an instance attribute
self.age = age # 'age' is an instance attribute

@property
def name(self):
return self._name

@name.setter
def name(self, name):
self._name = name

dog1 = Dog("Buddy", 2)
dog1.name = "Rex" #indirect call to @name.setter method

print(dog1.name) #Output is gonna be "Rex"

What are the differences between class and instance attributes?

The primary distinction between class and instance attributes lies in their scope and how they are accessed and modified.

Scope: for class attributes, it can be acces trhough every instance of the class, because it belongs to the class itself, not to any individual object. The exact opposite applies to instance attributes

Definition: Both can be definid in the __init__ constructor method, but class attributes can also be defined directly in the class body, outside of any methods. For instance attributes, you can define them after creating an instance of the object.

What are the advantages and drawbacks of each of them

For class attributes, we can say that they are more efficient from a memory usage perspective, since its shared by all instances of the same class. Its also easy to update, maintain values and maintain consistency through all the objects of the same class.

Its not all advantages tho. A drawback we can mention is how it lacks flexibility. The reason is the same: it shares the value across every object of the class

For instance attributes, we can say ther are somehow less efficient since it consumes more memory when accessing them. Homewever, the are more flexible and have a great advantage: encapsulation! Different attributes have differente access levels.

How does Python deal with the object and class attributes using the __dict__?

Every Python object has a hidden __dict__ attribute—a dictionary that stores its attributes. This is Python's fundamental mechanism for attribute management.

Every object has two dictionaries:
- Instance __dict__: Personal storage per object
- Class __dict__: Shared blueprint for all objects

class Demo:
class_val = "shared" # Class __dict__

def __init__(self, val):
self.inst_val = val # Instance __dict__
obj = Demo("personal")
print(obj.__dict__) # {'inst_val': 'personal'}
print(Demo.__dict__) # {'class_val': 'shared', …}

How Python Looks Up Attributes

When you access `obj.attribute`, Python searches:

Instance __dict__ -> Personal attributes

Class __dict__ -> Shared attributes

Parent classes -> Inheritance chain

class Base:
value = "base"
class Child(Base):
def __init__(self):
self.value = "instance" # Shadows class
obj = Child()
print(obj.value) # 'instance' (from instance __dict__)

Instance attributes override class attributes:

class Shared:
data = "class_version" # Class __dict__
obj = Shared()
obj.data = "instance_version" # Instance __dict__
print(obj.data) # 'instance_version' (instance wins)

--

--