在 Python 里,通常我们访问对象的属性(比如 obj.x),就像是从货架上直接拿东西,没有任何阻拦。
但是,如果你想在拿东西(读取)或放东西(写入)的时候搞点'小动作'——比如参数检查、日志记录、或者动态计算——你就需要一个'看门大爷'。
这个'看门大爷',就是描述符 (Descriptor)。
一、核心概念:什么是描述符?
在 Python 对象模型里,描述符就是一个把'属性访问'变成'方法调用'的代理类。
只要一个类实现了以下任意一个魔术方法,它生成的对象就是描述符:
__get__:有人要读属性时触发(对应val = obj.x)。__set__:有人要改属性时触发(对应obj.x = val)。__delete__:有人要删属性时触发(对应del obj.x)。
形象比喻
- 普通属性:像公共储物柜。你也拿,我也拿,谁都能塞进去任何东西(甚至塞个垃圾数据)。
- 描述符:像银行柜台。
- 你想存钱?(
__set__):柜员会检查钞票真伪(数据校验)。 - 你想取钱?(
__get__):柜员会核对你的身份,甚至计算利息给你(动态计算)。
- 你想存钱?(
二、三大金刚详解(怎么用?)
我们通过写一个**'强类型检查器'来演示。假设你需要定义一个学生类,要求分数必须是 0-100 的整数**。
1. 定义描述符类(制定规则)
这是'看门大爷'的自我修养。
class ScoreDescriptor:
def __init__(self, subject_name):
self.subject_name = subject_name
# 我们用一个私有变量名来存真正的数据,防止死循环
self.internal_name = "_" + subject_name
# 【读】当有人访问 student.math 时
def __get__(self, instance, owner):
# instance: 就是那个 student 对象 (如果是 Student.math 访问,这里是 None)
# owner: 就是 Student 类本身
print(f"🕵️ [GET] 正在查看 {self.subject_name} 成绩...")
instance :
(instance, .internal_name, )
():
()
(value, ):
TypeError()
( <= value <= ):
ValueError()
(instance, .internal_name, value)
():
()
(instance, .internal_name)

