ZetCode

Python __delete__ 方法

最后修改于 2025 年 4 月 8 日

本综合指南探讨了 Python 的 __delete__ 方法,这是一个控制属性删除的特殊方法。我们将涵盖描述符、属性以及属性管理的实际示例。

基本定义

__delete__ 方法是 Python 描述符协议的一部分。当使用 del 语句删除属性时,它会被调用。

主要特征:它在描述符类中定义,将实例作为参数(通常命名为 instance),并控制删除属性时发生的情况。它与 __get____set__ 一起使用,以实现完整的属性管理。

带有 __delete__ 的基本描述符

这是一个简单的描述符实现,展示了 __delete__ 的作用。当管理的属性被删除时,该方法会被调用。

basic_delete.py
class LoggedDelete:
    def __get__(self, instance, owner):
        print("Getting value")
        return instance._value
    
    def __set__(self, instance, value):
        print("Setting value")
        instance._value = value
    
    def __delete__(self, instance):
        print("Deleting value")
        del instance._value

class MyClass:
    attr = LoggedDelete()

obj = MyClass()
obj.attr = 42  # Calls __set__
val = obj.attr  # Calls __get__
del obj.attr    # Calls __delete__

此示例演示了完整的描述符协议。当我们删除 obj.attr 时,Python 会调用 __delete__ 方法。

LoggedDelete 描述符记录所有操作,并在实例的 _value 属性中管理实际的值存储。

阻止属性删除

__delete__ 可用于通过在尝试删除时引发异常来阻止属性删除。

prevent_delete.py
class ImmutableAttribute:
    def __get__(self, instance, owner):
        return instance._protected_value
    
    def __set__(self, instance, value):
        instance._protected_value = value
    
    def __delete__(self, instance):
        raise AttributeError("Cannot delete immutable attribute")

class Config:
    setting = ImmutableAttribute()

config = Config()
config.setting = "production"
print(config.setting)
# del config.setting  # Raises AttributeError

此实现使属性在创建后实际上是不可变的。尝试删除 setting 会引发 AttributeError

实际值存储在 _protected_value 中,而公共接口通过描述符协议控制访问。

类似属性的删除控制

property 装饰器也可以通过其 deleter 方法使用 __delete__。以下是如何实现类似的功能。

property_delete.py
class Temperature:
    def __init__(self, celsius):
        self._celsius = celsius
    
    @property
    def celsius(self):
        return self._celsius
    
    @celsius.setter
    def celsius(self, value):
        self._celsius = value
    
    @celsius.deleter
    def celsius(self):
        print("Resetting temperature")
        self._celsius = 0

temp = Temperature(25)
print(temp.celsius)  # 25
del temp.celsius     # Calls deleter
print(temp.celsius)  # 0

此示例显示了基于属性的属性删除控制方法。 @celsius.deleter 定义了删除属性时发生的情况。

此实现不是完全删除属性,而是在尝试删除时将温度重置为 0。

数据库支持的属性删除

__delete__ 可以与数据库等外部系统集成,以将属性删除作为持久操作来处理。

database_delete.py
class DatabaseField:
    def __init__(self, field_name):
        self.field_name = field_name
    
    def __get__(self, instance, owner):
        # In a real implementation, this would query the database
        return instance._data.get(self.field_name)
    
    def __set__(self, instance, value):
        # This would update the database
        instance._data[self.field_name] = value
    
    def __delete__(self, instance):
        # This would delete from the database
        print(f"Deleting {self.field_name} from database")
        instance._data.pop(self.field_name, None)

class User:
    name = DatabaseField('username')
    
    def __init__(self):
        self._data = {}  # Simulating database storage

user = User()
user.name = "Alice"
print(user.name)  # Alice
del user.name     # Calls __delete__
print(user.name)  # None

这个简化的示例展示了 __delete__ 在 ORM 中可能如何工作。实际的数据库操作使用字典进行模拟。

在实际的实现中,当删除属性时,__delete__ 将在数据库中执行 DELETE 操作。

延迟资源清理

__delete__ 可以在删除属性时管理资源清理,确保正确释放系统资源。

resource_delete.py
class ManagedFile:
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return open(self.filename, 'r').read()
    
    def __set__(self, instance, value):
        with open(self.filename, 'w') as f:
            f.write(value)
    
    def __delete__(self, instance):
        print(f"Cleaning up {self.filename}")
        try:
            import os
            os.remove(self.filename)
        except FileNotFoundError:
            pass

class Document:
    content = ManagedFile()
    
    def __init__(self, filename):
        self.filename = filename

doc = Document("test.txt")
doc.content = "Hello World"
print(doc.content)
del doc.content  # Deletes the file

此示例显示了 __delete__ 在删除属性时处理文件清理。该文件将从文件系统中删除。

ManagedFile 描述符处理文件操作和清理,展示了 __delete__ 如何管理资源生命周期。

最佳实践

资料来源

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。到目前为止,我已经撰写了 1,400 多篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有 Python 教程