Python delattr() 函数

Python delattr() 语法

delattr() 是 Python 的一个内置函数,它用于删除对象的属性或方法。

语法:

delattr(object, name)

说明:

delattr() 函数接收以下 2 个参数。

  • object(必选):是一个对象,比如类、对象(实例)、模块等。
  • name(必选):是一个属性名,它是一个字符串(区分大小写)。

delattr() 不返回任何值,它只删除对象的属性(如果对象允许的话)。如果指定的属性不存在,则 delattr() 会引发 AttributeError 异常。

实际上,下面 2 种方式是等价的。

# 方式 1
delattr(object, name)

# 方式 2
del object.name

delattr() 主要用于需要动态删除属性的场景,即属性名在运行时才能确定。如果属性名是固定的,通常直接使用 del object.name 会更简洁。

注意:

  • 无法使用 delattr() 删除内置类型(如 int、str)的实例的属性,否则会触发 AttributeError 异常。
  • 如果类使用 __slots__ 限制属性,则无法使用 delattr() 删除未在 __slots__ 中声明的属性。

Python delattr() 摘要

使用频率
官方文档 查看
相关函数 hasattr()getattr()setattr()

Python delattr() 示例

接下来,我们通过几个简单的例子来讲解一下 Python delattr() 函数是如何使用的。

注意: 由于绿叶网的 Python 在线编译器本身存在局限性,即如果测试代码报错,则只会返回报错信息(而不会返回其他结果)。因此为了得到更准确的结果,请小伙伴们在本地编辑器中测试本节示例代码。

示例 1:delattr() 删除对象属性

class Hero():
    def __init__(self, name, type):
        self.name = name
        self.type = type
    def skill(self):
        print(f'{self.name}开始放大招!')

h = Hero('船长', '力量型')
print(h.name)

delattr(h, 'name')
print(h.name)

运行结果如下。

船长
(报错) AttributeError: 'Hero' object has no attribute 'name'

分析:

想要删除对象的属性,除了使用 delattr() 函数之外,还可以使用 del 运算符来实现。

示例 2:del 删除对象属性

class Hero():
    def __init__(self, name, type):
        self.name = name
        self.type = type
    def skill(self):
        print(f'{self.name}开始放大招!')

h = Hero('船长', '力量型')
print(h.name)

del h.name
print(h.name)

运行结果如下。

船长
(报错) AttributeError: 'Hero' object has no attribute 'name'

示例 3:delattr() 删除类属性

class Hero:
    type = '船长'

print(Hero.type)      # 输出:船长
delattr(Hero, 'type')
print(Hero.type)      # 抛出 AttributeError

运行结果如下。

船长
(报错) AttributeError: type object 'Hero' has no attribute 'type'

示例 4:delattr() 删除私有属性

class Secure:
    def __init__(self):
        self.__key = 'secret'

s = Secure()
delattr(s, '_Secure__key')
print(hasattr(s, '_Secure__key'))      # 输出:False

运行结果如下。

False

深入理解 delattr()

要更深入地理解 delattr() 函数,我们需要探讨它与 Python 对象的底层机制,包括魔法方法和 __slots__ 的交互。

1. 与 __delattr__() 魔法方法的交互

在 Python 中,__delattr__() 是一个特殊的 “魔术方法”,它允许你自定义对象属性的删除行为。当使用 delattr() 函数或 del 关键字尝试删除对象的某个属性时,Python 实际上会在内部调用该对象的 __delattr__() 方法。

通过覆盖这个魔术方法,我们可以添加自定义的逻辑,比如:

  • 阻止特定属性被删除。
  • 在删除前执行清理操作。
  • 记录属性删除事件。

示例 5:使用 __delattr__() 阻止属性删除

class Protected:
    def __init__(self):
        self._data = '敏感数据'
    
    def __delattr__(self, name):
        if name == '_data':
            raise PermissionError('禁止删除敏感属性')
        super().__delattr__(name)

p = Protected()
delattr(p, '_data')

运行结果如下。

(报错)PermissionError: 禁止删除敏感属性

分析:

在 Protected 类中,我们重写了 __delattr__() 方法。当尝试删除 _data 属性时,自定义的 __delattr__() 会检测到这个属性名并抛出 PermissionError 异常,从而成功阻止了删除操作。

2. __slots__ 的限制

__slots__ 是 Python 中一个用于优化内存使用并限制实例属性的机制。当你在类中定义 __slots__ 时,Python 不再为每个实例创建传统的 __dict__(用于存储实例属性的字典),而是只为 __slots__ 中声明的属性分配空间。这样做有几个关键影响:

  • 内存优化:显著减少每个实例的内存占用,尤其是在创建大量实例时。
  • 属性限制:实例只能拥有 __slots__ 中声明的属性。你无法动态添加未在 __slots__ 中声明的新属性。
  • 删除限制:只能删除 __slots__ 中已声明的属性。尝试删除未声明的属性,或删除 __slots__ 中不存在的属性,都将导致 AttributeError 异常。

示例 6:__slots__ 对 delattr() 的限制

class Restricted:
    __slots__ = ['x']    # 只有 'x' 可以作为实例属性

r = Restricted()
r.x = 10
delattr(r, 'x')      # 允许
delattr(r, 'y')      # 抛出 AttributeError

运行结果如下。

(报错)AttributeError: 'Restricted' object has no attribute 'y' and no __dict__ for setting new attributes

常见问题

1. 如何安全删除可能不存在的属性?

我们可以先使用 hasattr() 进行判断该属性是否存在,然后再使用 delattr() 来进行删除。比如:

if hasattr(obj, 'attr'):
    delattr(obj, 'attr')

2. 删除方法是否会影响其他实例?

如果删除的是类方法,会影响所有实例。如果删除的是实例方法,只会影响当前实例。

3. 能否删除模块的属性?

可以,但需要谨慎操作。比如:

import sys

module = sys.modules[__name__]
setattr(module, 'TEMP', 100)
delattr(module, 'TEMP')

上一篇: setattr()

下一篇: super()

给站长反馈

绿叶网正在不断完善中,小伙伴们如果发现任何问题,还望多多给站长反馈,谢谢!

邮箱:lvyenet@vip.qq.com

「绿叶网」服务号
绿叶网服务号放大
关注服务号,微信也能看教程。
绿叶网服务号