Python __delattr__ Method
Last modified April 8, 2025
This comprehensive guide explores Python's __delattr__ method, the
special method invoked during attribute deletion. We'll cover basic usage,
attribute protection, descriptor interaction, and practical examples.
Basic Definitions
The __delattr__ method is called when an attribute deletion is
attempted on an object. It intercepts all del obj.attr operations.
This allows customization of attribute deletion behavior.
Key characteristics: it receives the attribute name as string, must call
super().__delattr__() for normal deletion, and can prevent
deletion of specific attributes. It works with __setattr__ and
__getattr__ for full attribute control.
Basic __delattr__ Implementation
Here's a simple implementation showing how __delattr__ intercepts
attribute deletion. The method is called whenever del is used on
an instance attribute.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def __delattr__(self, name):
print(f"Deleting attribute: {name}")
super().__delattr__(name)
p = Person("Alice", 30)
del p.age # Triggers __delattr__
print(hasattr(p, 'age')) # False
This example shows the basic interception of attribute deletion. The method prints a message before delegating to the parent class's implementation for actual deletion. Without calling super, the attribute wouldn't be deleted.
The super().__delattr__(name) call is crucial - it performs the
actual attribute removal from the instance's __dict__.
Preventing Attribute Deletion
__delattr__ can protect certain attributes from being deleted by
raising an AttributeError when deletion is attempted.
class ProtectedData:
def __init__(self, data, protected=False):
self.data = data
self.protected = protected
def __delattr__(self, name):
if name == 'data' and self.protected:
raise AttributeError("Cannot delete protected attribute 'data'")
super().__delattr__(name)
pd = ProtectedData("secret", protected=True)
# del pd.data # Raises AttributeError
del pd.protected # Works fine
This class prevents deletion of the data attribute when the
protected flag is True. Attempting to delete it raises an
AttributeError with a custom message.
This pattern is useful for creating classes with critical attributes that shouldn't be accidentally deleted during program execution.
Logging Attribute Deletion
__delattr__ can log attribute deletions for debugging or auditing
purposes, tracking when and which attributes are removed.
class LoggedDeletions:
def __init__(self, **kwargs):
for k, v in kwargs.items():
setattr(self, k, v)
def __delattr__(self, name):
print(f"LOG: Deleting attribute '{name}' at {time.ctime()}")
super().__delattr__(name)
import time
obj = LoggedDeletions(x=10, y=20)
del obj.x # Logs the deletion
print(vars(obj)) # Shows remaining attributes
This implementation logs all attribute deletions with a timestamp. The actual deletion still occurs via the parent class's implementation after logging.
Such logging can be valuable for debugging complex object lifecycles or monitoring sensitive data handling in applications.
Descriptor Interaction with __delattr__
When working with descriptors, __delattr__ allows custom behavior
when descriptor attributes are deleted, complementing __delete__.
class Descriptor:
def __delete__(self, instance):
print("Descriptor __delete__ called")
class MyClass:
desc = Descriptor()
def __delattr__(self, name):
print(f"MyClass __delattr__ for {name}")
super().__delattr__(name)
obj = MyClass()
del obj.desc # Calls both methods
This example shows the interaction between __delattr__ and
descriptor's __delete__. Both methods are called when deleting
a descriptor attribute, with __delattr__ called first.
The order is: __delattr__ intercepts the deletion, then the
descriptor's __delete__ is called if present, and finally the
actual attribute removal occurs.
Dynamic Attribute Cleanup
__delattr__ can perform additional cleanup when attributes are
deleted, such as closing files or releasing resources associated with them.
class ResourceHolder:
def __init__(self):
self.file = open('temp.txt', 'w')
self.cache = {}
def __delattr__(self, name):
if name == 'file' and hasattr(self, 'file'):
print("Closing file before deletion")
getattr(self, 'file').close()
super().__delattr__(name)
rh = ResourceHolder()
del rh.file # Closes the file first
# File is now properly closed before deletion
This class ensures proper cleanup when file attributes are deleted. The
__delattr__ method checks if the attribute being deleted is a
file and closes it before proceeding with deletion.
This pattern helps prevent resource leaks when attributes holding resources are deleted from instances.
Best Practices
- Always call super().__delattr__: Unless intentionally blocking deletion
- Be careful with recursion: Avoid attribute access in __delattr__ that might recurse
- Document protected attributes: Clearly document which attributes cannot be deleted
- Consider performance: Complex __delattr__ logic can slow down attribute deletion
- Use sparingly: Only implement when you need special deletion behavior
Source References
Author
List all Python tutorials.