Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A class attribute is a variable bound to a class object rather than to a specific instance of that class. It is defined within the class body, outside of any instance methods (such as __init__), and its memory allocation is shared across all instances instantiated from that class. Because class attributes are defined within the lexical scope of the class body, they reside in the class’s namespace (ClassName.__dict__) rather than the instance’s namespace (instance.__dict__).
class ExampleClass:
    # This is a class attribute
    shared_state = "initial_value" 

    def __init__(self, value):
        # This is an instance attribute
        self.instance_state = value 

Attribute Resolution Order

When you access an attribute via an instance (obj.attribute), Python invokes __getattribute__ and follows a strict resolution order:
  1. It first checks the class hierarchy, traversing the Method Resolution Order (__mro__), for a data descriptor (an object defining both __get__ and __set__ methods, such as a @property).
  2. If no data descriptor is found, it checks the instance’s namespace (obj.__dict__).
  3. If the attribute is not found in the instance namespace, it searches the class hierarchy sequentially according to the MRO (where the immediate class is simply the first element in this sequence), looking for a non-data descriptor or a regular class attribute.
This mechanism allows instances to read class attributes as if they were their own, provided they are not shadowed by an instance attribute or intercepted by a data descriptor.
obj1 = ExampleClass("A")
obj2 = ExampleClass("B")


# Accessing via the class
print(ExampleClass.shared_state)  # Output: initial_value


# Accessing via the instance (resolved via MRO fallback)
print(obj1.shared_state)          # Output: initial_value

Modification and Shadowing

The behavior of modifying a class attribute depends strictly on whether the modification is performed via the class object or the instance object, and whether the assignment operation is a reassignment or a mutation. 1. Modifying via the Class Assigning a new value directly to the class attribute updates the value in the class namespace. This change is immediately reflected across all instances that do not have a shadowing instance attribute.
ExampleClass.shared_state = "modified_by_class"
print(obj1.shared_state)  # Output: modified_by_class
print(obj2.shared_state)  # Output: modified_by_class
2. Reassigning via an Instance (Shadowing) Assigning a value to a class attribute via an instance does not modify the class attribute. Instead, it creates a new instance attribute with the same name in that specific instance’s __dict__. This new instance attribute “shadows” the class attribute for that specific object during lookup (Step 2 of the resolution order).

# Creates an instance attribute 'shared_state' in obj1
obj1.shared_state = "shadowed_by_instance"

print(obj1.shared_state)          # Output: shadowed_by_instance (reads from obj1.__dict__)
print(obj2.shared_state)          # Output: modified_by_class (reads via MRO)
print(ExampleClass.shared_state)  # Output: modified_by_class
3. Mutating a Mutable Class Attribute via an Instance If a class attribute is a mutable object (like a list or dict), calling a mutating method (e.g., .append(), .update()) via an instance modifies the shared object in place. Because no assignment (=) occurs to the attribute name itself, Python does not create a shadowing instance attribute.
class MutableExample:
    shared_list = []

m1 = MutableExample()
m2 = MutableExample()


# Mutating the shared object in place
m1.shared_list.append("new_item")

print(m2.shared_list)             # Output: ['new_item']
print(MutableExample.shared_list) # Output: ['new_item']
Master Python with Deep Grasping Methodology!Learn More