10 Practical Python Metaprogramming Scenarios Using __getattr__, __setattr__, Property Decorators, Descriptors, and Metaclasses
This article demonstrates ten practical Python metaprogramming techniques—including dynamic attribute access with __getattr__, attribute assignment with __setattr__, descriptor-based validation, property decorators, dynamic class and method creation, and metaclass usage—providing complete code examples for each scenario.
Metaprogramming in Python enables creating, modifying, or manipulating program structure and behavior at runtime. The article presents ten practical scenarios that illustrate how to use __getattr__ , __setattr__ , descriptors, property decorators, dynamic class creation, dynamic method creation, and metaclasses.
1. Using __getattr__ to retrieve dynamic attributes:
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) # raises AttributeError2. Using __setattr__ to set dynamic attributes and log assignments:
class DynamicAttributes:
def __setattr__(self, name, value):
print(f"Setting {name} to {value}")
super().__setattr__(name, value)
obj = DynamicAttributes()
obj.dynamic_attribute = 10 # Output: Setting dynamic_attribute to 103. Implementing attribute access control with 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 # raises ValueError4. Dynamically creating an attribute with setattr :
class MyClass:
pass
obj = MyClass()
setattr(obj, "dynamic_attribute", 10)
print(obj.dynamic_attribute) # 105. Dynamically deleting an attribute with delattr :
class MyClass:
dynamic_attribute = 10
obj = MyClass()
delattr(obj, "dynamic_attribute")
print(obj.dynamic_attribute) # raises AttributeError6. Creating a computed property using 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.57. Using @property together with a setter to control 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 # raises ValueError8. Dynamically creating a class with type :
MyClass = type("MyClass", (), {"dynamic_attribute": 10})
obj = MyClass()
print(obj.dynamic_attribute) # 109. Dynamically creating a method and attaching it to a class:
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 method10. 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"
else:
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 methodThese examples illustrate common applications of attribute access and dynamic attributes in Python, and can be adapted or extended for specific needs.
Test Development Learning Exchange
Test Development Learning Exchange
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.