0

0

Python 属性描述符 descriptor 原理

舞姬之光

舞姬之光

发布时间:2026-02-25 20:19:02

|

932人浏览过

|

来源于php中文网

原创

Python属性描述符本质是通过__get__/__set__/__delete__方法控制属性访问,依据查找顺序(类属性优先于实例属性)触发;数据描述符(含__set__)覆盖实例属性,非数据描述符(仅__get__)可被实例属性遮蔽。

python 属性描述符 descriptor 原理

Python 属性描述符(descriptor)的本质,是通过类的特殊方法(__get____set____delete__)控制对实例属性的访问逻辑。它不是语法糖,而是 Python 属性查找机制中明确参与的一环——当访问某个属性时,如果该属性是一个实现了至少一个描述符方法的对象,且被定义在类的命名空间中(而非实例字典里),解释器就会触发对应的方法。

描述符为什么能接管属性访问

关键在于 Python 的属性查找顺序(MRO 中的类属性优先于实例属性)。当执行 obj.attr 时,解释器按如下逻辑处理:

  • 先在 obj.__class__.__dict__ 中查找 attr
  • 如果找到且该对象有 __get__ 方法(即它是“非数据描述符”或“数据描述符”),就调用 attr.__get__(obj, type(obj))
  • 如果是“数据描述符”(同时定义了 __set____delete__),它会**覆盖**实例字典中的同名项(即 obj.__dict__['attr'] 完全无效)
  • 只有当类中没找到描述符,才会去查 obj.__dict__

数据描述符 vs 非数据描述符的区别

这个区分直接影响属性行为,是理解 descriptor 的核心:

  • 数据描述符:实现了 __set____delete__(哪怕只实现其中一个);它优先级最高,能屏蔽实例字典里的同名属性
  • 非数据描述符:只实现了 __get__;当实例字典中存在同名 key 时,会直接返回实例值,跳过 __get__

例如:property 是数据描述符(内部含 __set__),所以 @property 定义的属性不能被实例赋值覆盖;而函数对象是典型的非数据描述符,所以方法调用走的是 func.__get__(obj, cls),但你仍可给实例设 obj.func = 42 来遮蔽它。

立即学习Python免费学习笔记(深入)”;

Bardeen AI
Bardeen AI

使用AI自动执行人工任务

下载

手动写一个有用的描述符

比如实现一个带类型校验的属性:

class Typed:
    def __init__(self, expected_type):
        self.expected_type = expected_type
        self.name = None  # 后续由 __set_name__ 填充(Python 3.6+)
<pre class="brush:php;toolbar:false;">def __set_name__(self, owner, name):
    self.name = name

def __set__(self, obj, value):
    if not isinstance(value, self.expected_type):
        raise TypeError(f'{self.name} must be {self.expected_type.__name__}')
    obj.__dict__[self.name] = value

def __get__(self, obj, owner):
    if obj is None:
        return self
    return obj.__dict__.get(self.name)

使用

class Person: name = Typed(str) age = Typed(int)

p = Person() p.name = "Alice" # OK p.age = 30 # OK p.age = "30" # TypeError

注意:__set_name__ 是可选的,用于自动获取属性名,避免手动传参;实际存取仍通过实例字典完成,保证效率。

常见内置描述符和使用场景

很多 Python 特性底层都基于描述符:

  • property:最常用的数据描述符,封装 getter/setter/deleter
  • classmethodstaticmethod:非数据描述符,影响绑定行为(cls / 无绑定)
  • 函数对象本身:也是非数据描述符,所以 obj.method 触发 method.__get__(obj, cls) 返回绑定方法
  • 第三方库如 attrsdataclasses 内部也大量依赖描述符做字段管理

理解描述符,等于看懂了 Python “属性访问”这层抽象背后的执行链路——它不神秘,只是把控制权交给了开发者定义的对象。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

850

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

584

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

294

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

210

2025.08.29

class在c语言中的意思
class在c语言中的意思

在C语言中,"class" 是一个关键字,用于定义一个类。想了解更多class的相关内容,可以阅读本专题下面的文章。

707

2024.01.03

python中class的含义
python中class的含义

本专题整合了python中class的相关内容,阅读专题下面的文章了解更多详细内容。

22

2025.12.06

batoto漫画官网入口与网页版访问指南
batoto漫画官网入口与网页版访问指南

本专题系统整理batoto漫画官方网站最新可用入口,涵盖最新官网地址、网页版登录页面及防走失访问方式说明,帮助用户快速找到batoto漫画官方平台,稳定在线阅读各类漫画内容。

127

2026.02.25

Steam官网正版入口与注册登录指南_新手快速进入游戏平台方法
Steam官网正版入口与注册登录指南_新手快速进入游戏平台方法

本专题系统整理Steam官网最新可用入口,涵盖网页版登录地址、新用户注册流程、账号登录方法及官方游戏商店访问说明,帮助新手玩家快速进入Steam平台,完成注册登录并管理个人游戏库。

18

2026.02.25

TypeScript全栈项目架构与接口规范设计
TypeScript全栈项目架构与接口规范设计

本专题面向全栈开发者,系统讲解基于 TypeScript 构建前后端统一技术栈的工程化实践。内容涵盖项目分层设计、接口协议规范、类型共享机制、错误码体系设计、接口自动化生成与文档维护方案。通过完整项目示例,帮助开发者构建结构清晰、类型安全、易维护的现代全栈应用架构。

15

2026.02.25

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.4万人学习

Django 教程
Django 教程

共28课时 | 4.5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.7万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号