学过 Python 教程,我们知道,对象的属性可以使用 del 语句删除:

del my_object.an_attribute

其实,使用 Python 编程时不常删除属性,通过特性删除属性更少见。但是,Python 支持这么做,我可以虚构一个示例,演示这种处理方式。

定义特性时,可以使用 @my_propety.deleter 装饰器包装一个方法,负责删除特性管理的属性。下面兑现承诺,虚构一个示例,说明如何定义特性删值方法,如示例 19-26 所示。

示例 19-26 blackknight.py:灵感来自电影《巨蟒与圣杯》中的黑衣骑士角色

class BlackKnight:

    def __init__(self):
        self.members = ['an arm', 'another arm',
                        'a leg', 'another leg']
        self.phrases = ["'Tis but a scratch.",
                        "It's just a flesh wound.",
                        "I'm invincible!",
                        "All right, we'll call it a draw."]

    @property
    def member(self):
        print('next member is:')
        return self.members[0]

    @member.deleter
    def member(self):
        text = 'BLACK KNIGHT (loses {})\n-- {}'
        print(text.format(self.members.pop(0), self.phrases.pop(0)))

blackknight.py 脚本的 doctest 在示例 19-27 中。

示例 19-27 blackknight.py:示例 19-26 的 doctest(黑衣骑士从不屈服)

>>> knight = BlackKnight()
>>> knight.member
next member is:
'an arm'
>>> del knight.member
BLACK KNIGHT (loses an arm)
-- 'Tis but a scratch.
>>> del knight.member
BLACK KNIGHT (loses another arm)
-- It's just a flesh wound.
>>> del knight.member
BLACK KNIGHT (loses a leg)
-- I'm invincible!
>>> del knight.member
BLACK KNIGHT (loses another leg)
-- All right, we'll call it a draw.

在不使用装饰器的经典调用句法中,fdel 参数用于设置删值函数。例如,在 BlackKnight 类的定义体中可以像下面这样创建 member 特性:

member = property(member_getter, fdel=member_deleter)

如果不使用特性,还可以实现低层特殊的 __delattr__ 方法处理删除属性的操作,参见 19.6.3 节。留给喜欢拖延的读者一个练习:虚构一个类,定义 __delattr__ 方法。

特性是个强大的功能,不过有时更适合使用简单的或底层的替代方案。在本章的最后一节中,我们将回顾 Python 为动态属性编程提供的部分核心 API。