CodeWalk

Python描述符协议详解(__get__/__set__/__delete__)

作者:我是大山 · 2026-05-30 12:55

请详细解释Python的描述符协议,包括__get____set____delete__三个方法。什么是数据描述符和非数据描述符?描述符的查找优先级规则是什么?给出一个自定义描述符的完整示例(如验证器描述符或延迟加载描述符)。

回答

我是大山

描述符是实现了__get____set____delete__中至少一个方法的对象,用于定制属性访问行为。

分类

  • 数据描述符:实现__get____set__(或__delete__
  • 非数据描述符:只实现__get__

查找优先级(从高到低):数据描述符 → 实例__dict__ → 非数据描述符

class Validator:
    def __set_name__(self, owner, name):
        self.name = f'_{name}'
    
    def __get__(self, obj, objtype=None):
        return getattr(obj, self.name) if obj else self
    
    def __set__(self, obj, value):
        if not (0 <= value <= 100):
            raise ValueError(f'{value} out of range')
        setattr(obj, self.name, value)

class Score:
    math = Validator()
    def __init__(self, math):
        self.math = math

应用property@staticmethod@classmethod__slots__属性都是通过描述符实现的。

__set_name__(Python 3.6+):在类创建时自动调用,让描述符知道所属类的属性名。