当前位置: 首页 > 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.jsqmd.com/news/988738/

相关文章:

  • 2026年绕线机厂家推荐榜:电线电缆/铜丝钢丝/高速伺服自动绕线机优质品牌深度解析 - 品牌发掘
  • 第 15 集:Claude Code上下文工程学 —— 根治“80% 问题”
  • 2026年6月佛山回收中央空调公司推荐,正规资质环保处理更合规 - 广东再生资源回收
  • 当信号与系统遇见深度学习:我用傅里叶变换和拉普拉斯算子,看懂了CNN的本质
  • 如何打造个人专属的数字记忆库:从微信数据到生活足迹的完整指南
  • Luminex多因子免疫检测技术革新,云克隆七因子体系实现Th1/Th2/Th17免疫平衡全景量化
  • 实现图片本地缓存,减少url重复请求
  • AZ系、ZK系、WE系——一张牌号选型对照,加四种成型工艺的匹配逻辑
  • 有哪些真正好用的降AIGC网站?能同时搞定知网查重和降低AIGC率的那种
  • 非技术背景AIPM技术学习攻略:不学废、不内卷、刚好够用
  • AIOps 智能日志模式挖掘与异常关联:从日志海洋到结构化洞察
  • 数据的加密与解密(23:32)
  • 微信聊天记录永久备份终极指南:用WeChatExporter完整保存你的数字记忆
  • 集合 USB,AI ENC,AEC,BF,全面功能的语音处理模组
  • 2026年腾讯云OpenClaw/Hermes Agent配置Token Plan保姆级教程分享
  • 光伏电缆厂家盘点:从资质产能看选型适配方向 - 互联网科技品牌测评
  • 深入探讨KDB+函数的秩和参数验证
  • RedPanda-CPP轻量级C/C++ IDE架构解析与性能优化对比
  • 2026深圳中央空调回收品牌推荐:标杆企业领衔TOP5权威榜单 - 广东再生资源回收
  • MySQL数据库零基础入门,数据库原理、SQL详解、库表操作、字段约束、基础查询全覆盖
  • 2026年 电热管源头厂家推荐榜单:模温机电热管/单头法兰式/双头高温/PET电热管专业选购指南 - 品牌发掘
  • 如何在Windows上高效读写Btrfs分区:实用跨平台文件系统指南
  • 阳朔西街高性价比民宿推荐,舒适体验等你来享
  • 阅卷老师每天要看多少份试卷?机器帮了多少忙
  • Django+Vue双端权限系统模板,内置全国三级行政区划与一键容器化部署能力
  • 如何用Sunshine打造你的个人游戏云:终极开源串流服务器指南
  • LPC800 USART ISP协议详解与实战:构建稳定现场固件升级方案
  • MC68HC908MR24 TIMB定时器与SPI模块实战配置与避坑指南
  • GitHub 上 Stars 最多的 8 个开源 AI Assistant 工具
  • 回文子串(Palindromic Substrings)—— 题解