Python 里的“看门大爷”:彻底搞懂描述符 (Descriptors)

在 Python 里,通常我们访问对象的属性(比如obj.x),就像是从货架上直接拿东西,没有任何阻拦。

但是,如果你想在拿东西(读取)或放东西(写入)的时候搞点“小动作”——比如参数检查、日志记录、或者动态计算——你就需要一个“看门大爷”。

这个“看门大爷”,就是描述符 (Descriptor)。


一、 核心概念:什么是描述符?

在 Python 对象模型里,描述符就是一个把“属性访问”变成“方法调用”的代理类。

只要一个类实现了以下任意一个魔术方法,它生成的对象就是描述符:

  1. __get__:有人要属性时触发(对应val = obj.x)。
  2. __set__:有人要属性时触发(对应obj.x = val)。
  3. __delete__:有人要属性时触发(对应del obj.x)。

形象比喻

  • 普通属性:像公共储物柜。你也拿,我也拿,谁都能塞进去任何东西(甚至塞个垃圾数据)。
  • 描述符:像银行柜台
  • 你想存钱?(__set__):柜员会检查钞票真伪(数据校验)。
  • 你想取钱?(__get__):柜员会核对你的身份,甚至计算利息给你(动态计算)。

二、 三大金刚详解(怎么用?)

我们通过写一个**“强类型检查器”来演示。假设你需要定义一个学生类,要求分数必须是 0-100 的整数**。

1. 定义描述符类(制定规则)

这是“看门大爷”的自我修养。

classScoreDescriptor: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}成绩...")ifinstanceisNone:returnself# 从 instance 的字典里把真值拿出来returngetattr(instance,self.internal_name,0)# 【写】当有人执行 student.math = 90 时def__set__(self,instance,value):print(f"👮 [SET] 正在批改{self.subject_name},分数为{value}")# --- 核心逻辑:拦截并检查 ---ifnotisinstance(value,int):raiseTypeError(f"{self.subject_name}分数必须是整数!")ifnot(0<=value<=100):raiseValueError(f"{self.subject_name}分数必须在 0-100 之间!")# 检查通过,存入 instance 的字典setattr(instance,self.internal_name,value)# 【删】当有人执行 del student.math 时def__delete__(self,instance):print(f"🗑️ [DEL] 删除{self.subject_name}成绩")delattr(instance,self.internal_name)

2. 使用描述符(聘请看门大爷)

注意:描述符必须定义在类属性(Class Attribute)层级

classStudent:# 聘请两个“看门大爷”分别管理 数学 和 英语math=ScoreDescriptor("math")english=ScoreDescriptor("english")def__init__(self,name,math_score,english_score):self.name=name# 这里看似是普通赋值,实际上触发了 math.__set__()self.math=math_score self.english=english_scoredef__repr__(self):returnf"Student(name={self.name}, math={self.math}, english={self.english})"

3. 运行效果(见证奇迹)

s1=Student("小明",85,92)# 输出:# 👮 [SET] 正在批改 math,分数为 85# 👮 [SET] 正在批改 english,分数为 92# --- 测试读取 ---print(s1.math)# 输出:# 🕵️ [GET] 正在查看 math 成绩...# 85# --- 测试非法赋值 ---try:s1.math=120# 超过 100 分exceptValueErrorase:print(f"\n❌ 报错啦:{e}")# 输出: ❌ 报错啦: math 分数必须在 0-100 之间!try:s1.english="A+"# 类型错误exceptTypeErrorase:print(f"❌ 报错啦:{e}")# 输出: ❌ 报错啦: english 分数必须是整数!

三、 为什么要用描述符?(C++ 视角)

你可能会问:“我在Student类里写个get_mathset_math不行吗?”

当然行,但描述符有两个巨大的优势:

  1. 保持 API 优雅
    使用者依然可以用s.math = 90这种自然的语法,而不是s.set_math(90)。这在 Python 这种动态语言里非常重要。
  2. 代码复用(DRY 原则)
    如果你有 10 个学科(Math, English, Physics…),用传统 Getter/Setter 你要写 10 遍检查逻辑(if value < 0…)。
    用描述符,你写一次ScoreDescriptor类,然后实例化 10 次就行了。
    这就好比:你不需要给每个房间都专门雇一个保安,你只需要雇一个保安公司(描述符类),然后给每个房间派个保安(实例)就行。

四、 你其实天天在用它

即使你没写过__get__,你也一直在用描述符:

  1. @property
    这是一个内置的描述符,它是把一个函数伪装成属性的最简单方式。
  2. 方法 (Methods)
    为什么def foo(self):定义在类里,通过实例obj.foo()调用时self就会自动传进去?
    因为函数(Function)本身就是一个实现了__get__的描述符!每次访问obj.foo__get__都会动态生成一个“绑定方法(Bound Method)”对象返回给你。
  3. Django / SQLAlchemy
    name = models.CharField(max_length=100)—— 这里的CharField就是个巨大的描述符,它负责把 Python 对象的数据转换成 SQL 语句。

五、 总结

  • 描述符=属性访问拦截器
  • __get__= 拦截读取,控制返回什么值。
  • __set__= 拦截赋值,控制能否写入、写入什么。
  • instance参数= 谁在调用我?(具体的对象实例)。
  • owner参数= 谁拥有我?(类本身)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1130761.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【成绩管理】基于matlab GUI学生成绩管理系统(含各学科最高低分 平均法 直方图 饼图)【含Matlab源码 14866期】

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到海神之光博客之家&#x1f49e;&#x1f49e;&#x1f49e;&#x1f49…

Z-Image-Turbo游戏角色立绘生成质量评估

Z-Image-Turbo游戏角色立绘生成质量评估 引言&#xff1a;AI角色生成的工程化实践需求 随着游戏开发周期不断压缩、美术资源成本持续攀升&#xff0c;AI辅助内容生成&#xff08;AIGC&#xff09;已成为游戏行业降本增效的关键技术路径。在众多应用场景中&#xff0c;角色立绘生…

1台高性能云图形工作站如何共享给6位SolidWorks设计师同时并发

在制造业数字化转型浪潮中&#xff0c;SolidWorks等三维设计软件的高效协作成为企业提升研发效率的关键。要将1台高性能云图形工作站通过云飞云共享云桌面共享给6位SolidWorks设计师同时并发使用&#xff0c;需从硬件配置、资源管理、软件部署、网络优化、安全管控五个方面进行…

科哥版Z-Image-Turbo社区贡献指南:快速搭建开发环境

科哥版Z-Image-Turbo社区贡献指南&#xff1a;快速搭建开发环境 如果你是一名开源贡献者&#xff0c;想要为科哥的Z-Image-Turbo二次开发版本贡献力量&#xff0c;但苦于配置开发环境和理解代码结构需要花费大量时间&#xff0c;那么这篇文章就是为你准备的。本文将详细介绍如何…

AI绘画商业化第一步:如何用预配置镜像快速部署Z-Image-Turbo WebUI服务

AI绘画商业化第一步&#xff1a;如何用预配置镜像快速部署Z-Image-Turbo WebUI服务 对于小型设计公司而言&#xff0c;将AI绘画能力整合到工作流程中能显著提升创意生产效率。Z-Image-Turbo作为一款高性能文生图模型&#xff0c;通过预配置镜像可实现零基础部署&#xff0c;本…

跟曹操学「管理」

好的管理者&#xff0c;不是没有缺点的圣人&#xff0c;而是能让一群有缺点的能人&#xff0c;把事办成的“总协调”。读史到建安五年十月&#xff0c;官渡。 曹操与袁绍对峙已数月&#xff0c;粮草将尽&#xff0c;士卒疲乏。一封许都来信更添压力&#xff1a;后方许多官员与袁…

武汉咸安坊:百年石库门里分,藏着汉口的城市记忆

在武汉汉口南京路与胜利街的交汇处&#xff0c;坐落着一片独特的建筑群——咸安坊。这里不仅是国内保存最完好的石库门建筑群之一&#xff0c;更是武汉特有的“里分”民居的典型代表。始建于1915年的咸安坊&#xff0c;以赭红砖墙、悬挑阳台和标志性的“月亮门”为外在形象&…

新研智材联合创始人CTO南凯:材料科学新纪元——AI大模型驱动研发效率倍增|2025极新AIGC峰会演讲实录

2025年12月26日&#xff0c;【想象2025极新AIGC峰会】在上海浦东浦软大厦成功召开。新研智材联合创始人&CTO南凯先生在会上做了题为《材料科学与通用模型结合的新纪元》的演讲&#xff0c;系统阐述了AI技术如何重塑材料研发范式。新研智材联合创始人&CTO 南凯南凯重点提…

从图片到Mask:M2FP处理流程完全解析

从图片到Mask&#xff1a;M2FP处理流程完全解析 &#x1f4d6; 技术背景与核心挑战 在计算机视觉领域&#xff0c;人体解析&#xff08;Human Parsing&#xff09; 是一项细粒度的语义分割任务&#xff0c;目标是将图像中的人体分解为多个具有明确语义的身体部位&#xff0c;…

M2FP模型在工业机器人中的应用:人机协作安全

M2FP模型在工业机器人中的应用&#xff1a;人机协作安全 引言&#xff1a;从人体解析到智能协作的安全边界 随着智能制造的深入发展&#xff0c;工业机器人正从传统的“隔离作业”向“人机共融”模式演进。在这一转型过程中&#xff0c;如何实时感知人类操作员的姿态与位置&…

金竹飞瀑谷:在瀑布深潭间,邂逅畲族的历史与风情

在江西省抚州市乐安县南部的群山之中&#xff0c;坐落着一处以瀑布群和原始森林风貌著称的景区——金竹飞瀑谷。这片区域也被称为金竹瀑布群&#xff0c;是国家4A级旅游景区&#xff0c;并曾获评“江西百景”之一。其核心景观是由大小26处瀑布组成的吓通瀑布群&#xff0c;总落…

springboot基于Android的个人健康管理系统

基于Spring Boot和Android的个人健康管理系统介绍 基于Spring Boot和Android的个人健康管理系统是一套结合后端高效服务与移动端便捷性的健康管理解决方案。该系统利用Spring Boot框架构建强大的后端服务&#xff0c;同时通过Android应用提供用户友好的交互界面&#xff0c;旨在…

YOLOv8优化:损失篇 | 原创自研 | 一种基于小目标改进的多尺度的动态(SD)损失

💡💡💡改进思路与核心逻辑 小目标检测的核心痛点是:小目标的 IoU 值本身偏低,且原 SDIoU 的惩罚项(距离 / 形状)对小目标过度惩罚,导致小目标的 IoU 得分被进一步压低。因此改进方向为: 增强小目标 IoU 权重:引入尺度因子,让小目标的基础 IoU 在最终得分中占比更…

新看点/818AI创始人冷煜:AI落地,决胜“最后100米” | 2025极新AIGC峰会演讲实录

2025年12月26日&#xff0c;【想象2025极新 AIGC 峰会】在上海浦东浦软大厦成功举办。新看点/818AI创始人冷煜先生在会上做了题为《企业落地 AI 生产力的最佳伙伴》的演讲。重点分享了818AI的发展情况、发展历程以及他们在AI办公赛道的实践心得。新看点/818AI创始人 冷煜冷煜重…

阿里通义Z-Image-Turbo WebUI与无障碍设计:如何生成适合视障人士的图像描述

阿里通义Z-Image-Turbo WebUI与无障碍设计&#xff1a;如何生成适合视障人士的图像描述 对于无障碍设计师来说&#xff0c;为视障人士生成准确的图像描述是一项重要但耗时的工作。手动编写这些描述不仅效率低下&#xff0c;还难以保证一致性。阿里通义Z-Image-Turbo WebUI提供了…

死锁(八股)

操作系统&#xff08;死锁产生条件&#xff09;&#xff1a;互斥条件&#xff1a;一个资源一次只能被一个进程使用持有并等待条件&#xff1a;一个进程因请求资源而阻塞时&#xff0c;对已获得资源保持不放不剥夺条件&#xff1a;进程获得的资源&#xff0c;在未完全使用完之前…

L3量产前夜:光互联要上车了?

L3 即在眼前&#xff0c;车上那根“主干线”要不要换成光&#xff1f;2026 年&#xff0c;对很多主机厂来说是一个微妙的时间点。当 L3 牌照的放行&#xff0c;逐步走向量产验证&#xff0c;感知的摄像头和激光雷达数量、像素和刷新频率都在往上叠&#xff0c;且对 Raw Data&am…

IO(八股)

IO流&#xff1a;程序与外部设备&#xff08;文件&#xff0c;内存&#xff0c;网络&#xff0c;外设&#xff09;之间传输数据的抽象方式。数据流向&#xff1a;输入流&#xff08;InputStream&#xff09;输出流&#xff08;OutputStream&#xff09;数据单位&#xff1a;字节…

低成本构建多语言网站:开源翻译镜像节省80%成本

低成本构建多语言网站&#xff1a;开源翻译镜像节省80%成本 在多语言网站的建设过程中&#xff0c;高质量的翻译服务是核心需求之一。然而&#xff0c;商业级翻译API&#xff08;如Google Translate、DeepL&#xff09;往往按字符计费&#xff0c;长期使用成本高昂&#xff0c…

零成本学习:利用免费GPU额度体验最新图像生成技术

零成本学习&#xff1a;利用免费GPU额度体验最新图像生成技术 作为一名经济拮据的大学生&#xff0c;想要学习AI创作却苦于没有高性能电脑和云计算预算&#xff1f;别担心&#xff0c;本文将带你利用各平台的免费GPU额度&#xff0c;零成本体验最新的图像生成技术。我们将以Sta…