Skip to content

Instance & Class Attributes

Attributes are the variables attached to a class or an instance. They represent the state of an object. In Python, attributes are incredibly dynamic, but understanding the difference between “belonging to the class” and “belonging to the instance” is vital.


These are unique to each individual object. They are almost always defined inside the __init__ method.

instance.py
class User:
def __init__(self, username):
self.username = username
u1 = User("Alice")
u2 = User("Bob")
# u1.username is different from u2.username

These are shared by all instances of a class. They are defined directly in the class body.

class_attr.py
class Airplane:
wings = 2 # Every airplane has 2 wings
def __init__(self, model):
self.model = model
a1 = Airplane("747")
a2 = Airplane("A380")
print(a1.wings) # 2
print(a2.wings) # 2

If you try to change a class attribute through an instance, you accidentally create a new instance attribute that hides (shadows) the class attribute for that one object.

a1.wings = 3 # This creates a NEW 'wings' attribute on a1 only!
print(Airplane.wings) # Still 2

3. Dynamic Attribute Access: getattr and setattr

Section titled “3. Dynamic Attribute Access: getattr and setattr”

Sometimes you don’t know the name of the attribute until the program is running (e.g., reading from a config file).

dynamic.py
attr_name = input("Which attribute to check? ") # e.g., 'model'
val = getattr(a1, attr_name, "Not found")
print(val)
setattr(a1, "color", "White")

By default, every Python object stores its attributes in a dictionary (__dict__). Dictionaries are fast, but they consume a lot of RAM because they are “over-allocated” to handle growth.

If you are creating millions of small objects (like points in a 3D simulation), the memory overhead of __dict__ can be massive. You can optimize this using __slots__.

slots_demo.py
class Point:
# This tells Python: "Only these two attributes exist.
# Do NOT create a __dict__ for this class."
__slots__ = ("x", "y")
def __init__(self, x, y):
self.x = x
self.y = y
  1. Memory: Significantly reduces the RAM usage per object.
  2. Speed: Attribute access is slightly faster.
  3. Safety: Prevents users from accidentally adding new, misspelled attributes (e.g., p.z = 10 would raise an AttributeError).

Attribute TypeScopeStorage
InstanceUnique to the object.instance.__dict__
ClassShared by all objects.Class.__dict__
SlotsFixed & Optimized.Fixed memory offsets.