Fundamentals 6 min read

10 Practical Python Metaprogramming Scenarios Using __getattr__, __setattr__, and Descriptors

This article presents ten useful Python metaprogramming examples that demonstrate dynamic attribute access, setting, descriptor‑based validation, runtime attribute creation and deletion, computed properties, dynamic class and method generation, and metaclass techniques for flexible program behavior.

Test Development Learning Exchange
Test Development Learning Exchange
Test Development Learning Exchange
10 Practical Python Metaprogramming Scenarios Using __getattr__, __setattr__, and Descriptors

Metaprogramming in Python allows programs to create, modify, or control their own structure at runtime; the following ten examples illustrate common use‑cases with __getattr__ , __setattr__ , and property descriptors.

1. Dynamic attribute retrieval with __getattr__ :

class DynamicAttributes:
    def __getattr__(self, name):
        if name == "dynamic_attribute":
            return "This is a dynamic attribute"
        else:
            raise AttributeError(f"{name} is not found")

obj = DynamicAttributes()
print(obj.dynamic_attribute)  # This is a dynamic attribute
print(obj.undefined_attribute)  # AttributeError: undefined_attribute is not found

2. Dynamic attribute assignment with __setattr__ :

class DynamicAttributes:
    def __setattr__(self, name, value):
        print(f"Setting {name} to {value}")
        super().__setattr__(name, value)

obj = DynamicAttributes()
obj.dynamic_attribute = 10  # Setting dynamic_attribute to 10

3. Attribute access control using a descriptor:

class PositiveNumber:
    def __get__(self, instance, owner):
        return instance.__dict__[self.name]
    def __set__(self, instance, value):
        if value <= 0:
            raise ValueError("Value must be positive")
        instance.__dict__[self.name] = value
    def __set_name__(self, owner, name):
        self.name = name

class MyClass:
    positive_number = PositiveNumber()

obj = MyClass()
obj.positive_number = 10
print(obj.positive_number)  # 10
obj.positive_number = -5  # ValueError

4. Dynamically creating an attribute with setattr :

class MyClass:
    pass

obj = MyClass()
setattr(obj, "dynamic_attribute", 10)
print(obj.dynamic_attribute)  # 10

5. Dynamically deleting an attribute with delattr :

class MyClass:
    dynamic_attribute = 10

obj = MyClass()
delattr(obj, "dynamic_attribute")
print(obj.dynamic_attribute)  # AttributeError

6. Creating a computed property with the @property decorator:

class Circle:
    def __init__(self, radius):
        self.radius = radius
    @property
    def area(self):
        return 3.14 * self.radius ** 2

circle = Circle(5)
print(circle.area)  # 78.5

7. Property with getter and setter for controlled access:

class PositiveNumber:
    def __get__(self, instance, owner):
        return instance.__dict__[self.name]
    def __set__(self, instance, value):
        if value <= 0:
            raise ValueError("Value must be positive")
        instance.__dict__[self.name] = value
    def __set_name__(self, owner, name):
        self.name = name

class MyClass:
    positive_number = PositiveNumber()
    def __init__(self):
        self._positive_number = 0
    @property
    def positive_number(self):
        return self._positive_number
    @positive_number.setter
    def positive_number(self, value):
        self._positive_number = value

obj = MyClass()
obj.positive_number = 10
print(obj.positive_number)  # 10
obj.positive_number = -5  # ValueError

8. Dynamically creating a class with type :

MyClass = type("MyClass", (), {"dynamic_attribute": 10})
obj = MyClass()
print(obj.dynamic_attribute)  # 10

9. Dynamically adding a method using type :

def dynamic_method(self):
    print("This is a dynamic method")

MyClass = type("MyClass", (), {"dynamic_method": dynamic_method})
obj = MyClass()
obj.dynamic_method()  # This is a dynamic method

10. Using a metaclass to provide dynamic attributes and methods:

class DynamicAttributes(type):
    def __getattr__(cls, name):
        if name == "dynamic_attribute":
            return "This is a dynamic attribute"
        raise AttributeError(f"{name} is not found")
    def dynamic_method(cls):
        print("This is a dynamic method")

class MyClass(metaclass=DynamicAttributes):
    pass

obj = MyClass()
print(obj.dynamic_attribute)  # This is a dynamic attribute
obj.dynamic_method()  # This is a dynamic method

These examples demonstrate how Python’s metaprogramming facilities can be leveraged for dynamic attribute handling, validation, computed properties, and runtime class or method generation, providing a flexible toolbox for advanced developers.

pythonmetaprogrammingcode examplespropertydescriptorsdynamic attributes
Test Development Learning Exchange
Written by

Test Development Learning Exchange

Test Development Learning Exchange

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.