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.