当前位置: 首页 > news >正文

描述符(Descriptors)‌

1. 什么是描述符?
描述符是 Python 面向对象编程中一个底层但极其强大的机制。简单来说,‌描述符是一个实现了特定协议(__get__, __set__, __delete__)的类‌。

当你把一个描述符类的实例赋值给另一个类的‌类属性‌时,Python 会自动拦截对该属性的访问、赋值和删除操作,从而让你能够自定义属性的行为。

它是 Python 中 property、classmethod、staticmethod 以及 super() 背后的实现原理。

2. 核心协议方法
一个完整的描述符通常实现以下三个方法中的至少一个:

‌__get__(self, obj, type=None)‌:当访问属性时被调用。
obj:拥有该属性的实例对象(如果是通过类访问,则为 None)。
type:拥有该属性的类。
‌__set__(self, obj, value)‌:当给属性赋值时被调用。
obj:拥有该属性的实例对象。
value:要赋的值。
‌__delete__(self, obj)‌:当删除属性时被调用。

3. 经典应用场景:类型检查与数据验证
假设你想创建一个 Person 类,要求 age 必须是整数且大于 0,name 必须是非空字符串。使用描述符可以完美解耦验证逻辑。

class TypedAttribute: """通用类型检查描述符""" def __init__(self, name, expected_type): self.name = name # 属性名,用于存储真实数据 self.expected_type = expected_type def __get__(self, obj, objtype=None): if obj is None: return self # 从实例的 __dict__ 中获取真实值 return obj.__dict__.get(self.name) def __set__(self, obj, value): if not isinstance(value, self.expected_type): raise TypeError(f"Expected {self.expected_type} for {self.name}, got {type(value)}") #将真实值存入实例的 __dict__ obj.__dict__[self.name] = value def __delete__(self, obj): raise AttributeError(f"Can't delete attribute {self.name}") class Person: # 将描述符实例化为类属性 name = TypedAttribute("name", str) age = TypedAttribute("age", int) def __init__(self, name, age): self.name = name # 触发 TypedAttribute.__set__ self.age = age # 触发 TypedAttribute.__set__ # 测试 p = Person("Alice", 30) print(p.name) # 输出: Alice (触发 __get__) try: del p.name except Exception as e: print(e) # 输出: Can't delete attribute name try: p.age = "thirty" # 触发 __set__,抛出异常 except TypeError as e: print(e) # 输出: Expected <class 'int'> for age, got <class 'str'>

4. 为什么这很重要?

a 代码复用与解偶‌:验证逻辑封装在 TypedAttribute 中,任何类都可以复用它,无需在每个类里重复写 if isinstance...。
‌b 控制属性访问权限‌:可以实现只读属性(只实现 __get__)、懒加载属性(第一次访问时才计算值)等高级功能。
c‌ 理解 Python 底层机制‌:掌握描述符是理解 Python 如何管理属性查找顺序(MRO + Descriptor Protocol)的关键。

5. 数据描述符 vs 非数据描述符

  • 数据描述符‌:实现了__set____delete__。优先级‌高于‌实例字典 (obj.__dict__)。
  • 非数据描述符‌:只实现了__get__。优先级‌低于‌实例字典。
    • 这就是为什么你可以用实例属性覆盖方法(方法是函数,属于非数据描述符),但不能覆盖property(property 是数据描述符)。

6 最佳实践建议
不要过度使用‌:对于简单的属性验证,内置的 @property 装饰器通常更简洁易读。
适用场景‌:当你需要在多个类中复用复杂的属性逻辑(如 ORM 框架中的字段映射、严格的类型系统、缓存机制)时,描述符是最佳选择。
注意命名冲突‌:在 __init__ 中给描述符传参时,务必确保存储数据的键名(如上面的 self.name)不与描述符本身的类属性名冲突,通常建议存储在 obj.__dict__ 中并使用唯一键名。

http://www.rkmt.cn/news/1500484.html

相关文章:

  • 2026年绕线机厂家推荐榜:电线电缆/铜丝钢丝/高速伺服自动绕线机优质品牌深度解析 - 品牌发掘
  • 第 15 集:Claude Code上下文工程学 —— 根治“80% 问题”
  • 如何打造个人专属的数字记忆库:从微信数据到生活足迹的完整指南
  • 非技术背景AIPM技术学习攻略:不学废、不内卷、刚好够用
  • AIOps 智能日志模式挖掘与异常关联:从日志海洋到结构化洞察
  • 光伏电缆厂家盘点:从资质产能看选型适配方向 - 互联网科技品牌测评
  • 2026年 电热管源头厂家推荐榜单:模温机电热管/单头法兰式/双头高温/PET电热管专业选购指南 - 品牌发掘
  • LPC800 USART ISP协议详解与实战:构建稳定现场固件升级方案
  • GitHub 上 Stars 最多的 8 个开源 AI Assistant 工具
  • 回文子串(Palindromic Substrings)—— 题解
  • 拆解 GEO 底层技术壁垒:融景科技凭借两项自研国家软著,服务中铁、华润、碧桂园等头部企业,打破湛江 AI 优化市场贴牌工具困局 - 广东科技观察
  • 2026年广东GEO优化推广榜单:豆包/元宝/DeepSeek AI平台搜索代运营,助力制造业工厂与灯具五金家具行业精准营销 - 品牌发掘
  • 规范用药能降73%死亡率,可惜很多心衰患者没坚持住
  • 告别Token烧钱焦虑!「秒云Tokens管家」智能预警,筑牢AI成本防线
  • [智能体-333]:LangGraph代码示例,详细注解:基础线性图、条件分支、循环、人在回路
  • 英雄联盟Akari助手:3个核心功能让你游戏效率提升500%的免费开源工具
  • 2026年 广东/东莞铁艺装饰花件厂家推荐榜:失蜡铸造花件、铁艺装饰花件源头工厂专业实力与精工匠心之选 - 品牌发掘
  • 孔夫子旧书网批量抓取工具:自动登录+商品信息提取+Excel导出
  • 北京配眼镜功能性镜片怎么选,五类场景逐一对照 - 配眼镜新资讯
  • 五指毛桃赤小豆膏:从古籍配伍到现代轻养生的配方逻辑
  • 完整指南:在macOS上轻松运行Windows程序的终极解决方案
  • 5 分钟上手:为 Cline 配置一个免费的 MCP 天气服务
  • 亚马逊流量转化专家哪家强?资深行业大咖与实战品牌盘点
  • 2026年重庆保姆服务TOP榜单:钟点家姆/住家保姆/育儿陪护/养老做饭阿姨精选推荐与口碑解析 - 企业推荐官【官方】
  • 2026重庆除甲醛公司真实有效推荐,附加推荐理由! - 空气捍卫者
  • 3个核心优势:DeepSeek-Coder-V2如何重塑开发者的编程体验
  • 计算机毕业设计之基于python的软件测试场景用例管理平台
  • 2026年AI编程助手选购指南与横向对比榜单
  • 测评|苏州企业服务公司做GEO应该怎么选服务商?靠谱GEO服务商推荐? - 极义GEO
  • 三步让老旧打印机秒变AirPrint无线打印神器:Docker容器终极指南