python 特殊属性及方法详细解析
前言「特殊属性」和「特殊方法」这两个词经常被混着用其实它们在语言参考里是两套不同的东西。特殊方法也叫魔术方法是那些会被语法隐式调用的、可调用的下划线方法比如__init__、__len__特殊属性是那些由解释器自动维护、通常不是可调用的数据成员比如__dict__、__class__、__module__、__qualname__。前者你写它是为了改变对象的行为后者你读它是为了反射introspection——看看这个对象到底是什么、从哪来、长什么样。初学者最常见的误解有三个。第一以为__doc__、__name__是普通属性随便就能改——本对象上有些能改有些不能类上的__dict__甚至是只读的映射代理。第二以为属性能不能拿到只看「类里有没有」忽略了实例字典优先这条查找顺序。第三以为__dict__一定存在——用了__slots__的实例就可能没有。本文按「属性住在哪里」这条线索把它们梳理清楚并配一张对照表区分属性和方法。一、先分清属性和方法的区别类别长什么样谁在维护典型代表你拿它干什么特殊属性数据成员多为只读或半只读解释器__dict__、__class__、__doc__、__module__、__qualname__反射、调试、序列化特殊方法可调用的方法你定义、解释器调用__init__、__repr__、__eq__、__enter__改变对象在语法下的行为普通属性普通数据成员你self.name存业务数据判断标准很简单能被语法自动触发的下划线成员是方法描述对象自身信息的是属性。当然边界不是绝对的——__init__也是属性它在类字典里只是它的值是个函数对象可以调用而已。理解反射的视角是类本身也是一个对象也有自己的__dict__。二、对象上的特殊属性# 适用于 Python 3.8class Config:配置对象的文档字符串。timeout 3def __init__(self, host):self.host hostcfg Config(localhost)print(cfg.__class__) # class __main__.Configprint(cfg.__dict__) # {host: localhost}——注意只有实例属性print(Config.__dict__[timeout]) # 3类属性在类字典里print(Config.__doc__) # 配置对象的文档字符串。几个必须记牢的点obj.__class__是这个实例所属的类type(obj)也能拿到但对象可以伪造__class__type()不会。obj.__dict__是实例的命名空间只装实例自己的属性看不到类属性。Config上的timeout不在实例字典里。Config.__dict__是映射代理mapping proxy提供类命名空间的只读视图你改不动它。__doc__来自类或函数/模块的第一条字符串字面量没写 docstring 时是None。三、实例属性与类属性的查找顺序语言参考把这条链路和描述符协议合起来看才完整。取obj.attr时1. 先在类型沿 MRO 向上里找同名成员若找到且它是数据描述符直接用它的结果实例字典被忽略2. 否则查实例命名空间 obj.__dict__3. 实例字典里也没有就用类型上找到的那个成员普通类属性或非数据描述符函数会被变成绑定到实例的方法对象4. 以上都找不到才调用类的 __getattr__如果定义了反直觉的地方在第 1 步数据描述符带__set__/__delete__的描述符比如property的优先级高于实例字典而普通属性包括函数属于非数据描述符会被实例字典盖住。所以「实例属性覆盖类属性」这条经验法则对数据描述符是无效的。# 适用于 Python 3.8class Demo:class_attr 我是类属性propertydef computed(self):return 我是数据描述符def method(self):return 我是方法d Demo()d.class_attr 我盖住了类属性 # 赋值只会写进实例字典不会改类字典print(d.class_attr) # 我盖住了类属性print(Demo.class_attr) # 我是类属性——类字典没变print(d.computed) # 我是数据描述符——property 优先级更高最后一行尤其重要即使你给d硬塞一个computed到实例字典里property作为数据描述符依然优先会抛AttributeError——这就是「实例属性覆盖类属性」这条经验法则的例外。四、类、函数、模块上的特殊属性同一套__name__/__qualname__/__module__/__doc__会出现在好几类对象上含义略有差异属性类type函数模块__name__类的名字函数名模块名__qualname__带外层作用域的限定名带外层作用域的限定名无模块用__name____module__定义该类的模块名定义该函数的模块名——__doc__类 docstring函数 docstring模块 docstring__dict__映射代理只读函数的命名空间模块的命名空间可写__qualname__qualified name限定名是 3.3 起引入的它带上了定义处的嵌套路径所以嵌在类或函数里的东西__name__只给最后一段__qualname__给完整路径。# 适用于 Python 3.8class Outer:class Inner:def method(self):passprint(Outer.Inner.__name__) # Innerprint(Outer.Inner.__qualname__) # Outer.Innerprint(Outer.Inner.method.__qualname__) # Outer.Inner.method__mro__是类上的另一个常用特殊属性它是方法解析顺序method resolution order的元组C.__mro__能让你一眼看出多重继承时到底先找谁。五、注解与 __slots__两个特殊的「声明式」属性__annotations__存的是对象上的注解通常是类型提示。语言参考明确提醒它是惰性求值的——访问这个属性本身可能执行任意代码、也可能抛异常从 3.14 起注解改为默认延迟求值。类、函数、模块都能有__annotations__但对没有注解的对象访问它行为与版本相关具体以官方文档为准。__slots__是一个纯声明式的类属性值可以是字符串、可迭代对象或字符串序列作用是显式声明实例会有哪些数据成员并阻止自动创建__dict__和__weakref__。它带来两个实际后果一是没有__dict__的实例不能挂新属性赋值会抛AttributeError二是数据成员固定下来之后内存占用和属性查找都可能更省。要注意的几个陷阱从没有__slots__的父类继承时子类实例照样有__dict____slots__用描述符实现所以不能靠类属性给 slot 变量设默认值给int、bytes、tuple这类变长内置类型定义非空__slots__会直接抛TypeError。__match_args__是 3.10 起配合结构化模式匹配用的类属性值是一个字符串元组让case MyClass(x, y)这种位置写法能映射到关键字。它的缺省等价于空元组。六、把反射用起来一个小例子# 适用于 Python 3.8class Invoice:一张发票。currency CNYdef __init__(self, amount):self.amount amountdef describe(obj):cls obj.__class__print(类名, cls.__name__)print(限定名, cls.__qualname__)print(定义于模块, cls.__module__)print(文档, cls.__doc__)print(实例属性, obj.__dict__)print(类属性键, sorted(k for k in cls.__dict__ if not k.startswith(__)))describe(Invoice(99))cls.__dict__里既能看到currency也能看到__init__——因为类的方法本质上就是存在类字典里的属性。这正是「属性和方法在底层是同一回事」的佐证区分它们的不是存储位置而是能不能被语法隐式调用。常见坑点❌ 以为obj.__dict__里能看到类属性。✅ 实例字典只装实例自己的属性类属性在type(obj).__dict__里要反射得查两处。❌ 给实例赋一个和数据描述符如property同名的属性指望能盖住它。✅ 数据描述符的优先级高于实例字典「实例属性覆盖类属性」在这类成员上不成立。❌ 认为所有实例都有__dict__。✅ 用了__slots__的类实例可能没有__dict__反射代码要先hasattr再访问。❌ 把type(obj).__dict__当普通字典去改。✅ 类的__dict__是只读的映射代理改它会报错要改类型属性用setattr并清楚自己在做什么。❌ 用__name__当对象的唯一标识。✅ 嵌套定义时__name__只有最后一段会重名限定名要用__qualname__3.3。❌ 给子类只写__slots__就以为省掉了__dict__。✅ 父类没有__slots__时子类实例依然有__dict__省内存的目标落空。❌ 直接用类属性给__slots__里的变量设默认值。✅__slots__是描述符实现的类属性会覆盖描述符赋值默认值拿不到默认值应写在__init__里。❌ 以为__annotations__一定是个现成的字典随手就读。✅ 它是惰性求值的访问可能触发代码执行甚至抛异常3.14 起注解默认延迟求值。总结属性住在哪关键性质__class__实例实例所属的类__dict__实例 / 类 / 函数 / 模块实例的可见写类的只读映射代理__name__类 / 函数 / 模块名字最后一段__qualname__类 / 函数带外层路径的限定名3.3__module__类 / 函数 / 方法定义处的模块名__doc__类 / 函数 / 模块文档字符串没有时为 None__mro__类方法解析顺序__slots__类声明式阻止创建__dict____annotations__类 / 函数 / 模块惰性求值3.14 起默认延迟__match_args__类配合模式匹配的位置参数3.10一句话区分特殊方法改变行为特殊属性暴露身份。写类时你关心前者做反射、调试、序列化时你关心后者。而把两者串起来的那条主线就是本节反复强调的查找顺序——实例字典先于非数据描述符的类属性却被数据描述符反超。

相关新闻

Winform仿QQ登录界面源码解析:无边框窗体与验证码实战

Winform仿QQ登录界面源码解析:无边框窗体与验证码实战

简介:一份基于Winform的QQ登录界面仿制源码,面向初学C#.NET桌面开发的读者,或需要快速搭建登录窗口的设计人员。项目完全使用Winform内置控件,如Label、TextBox、PictureBox和Button,不引入任何第三方组件,…

2026/11/11 12:50:46 阅读更多 →
N卡驱动与CUDA安装排查全攻略:从概念到多版本共存

N卡驱动与CUDA安装排查全攻略:从概念到多版本共存

驱动装对了,CUDA 却还是不能用——这个坑我替大家踩了无数遍。尤其是最近很多朋友从 WSL2、PyTorch、llama.cpp 这些入口接触 AI 开发,第一步就卡在"N 卡驱动 CUDA"上,越是新手越容易把这两件事搞混。这篇文章就把我从头到尾的安装…

2026/11/11 6:47:00 阅读更多 →
本地部署AI大模型:从需求梳理到硬件选型的完整避坑指南

本地部署AI大模型:从需求梳理到硬件选型的完整避坑指南

1. 先搞清楚“本地部署 AI”到底在部署什么 很多企业老板或者技术负责人一拍脑袋说“我们要本地部署 AI”,底下的人第一反应就是去查显卡价格、对比 A100 和 4090 的算力参数、研究机房机柜够不够放。这个顺序不能说全错,但大概率会让你在第一个月就花掉…

2026/11/10 16:32:57 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年,我大部分时间都在跟浏览器标签页打交道,直到第一次把桌面应用跑起来,才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词,最开始是在某段时间频繁出现在同事的讨论里,一个用HTML…

2026/11/10 23:32:01 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介:亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档,主要面向智能锁安装人员、终端用户及售后维护者,帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件,大小4.37MB,内容结构清晰&#xff…

2026/11/10 23:32:03 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统,整车要求空载跑到8m/s,电机转速已经拉到额定点,驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令,转速纹丝不动,三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/11/11 2:31:33 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年,用它写过嵌入式驱动、做过游戏服务端,也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词,我其实挺感慨的——这门语言的难点从来不是语法多,而是知识点之间的耦合太深…

2026/11/10 16:14:15 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介:亚太天能T109滑盖智能锁产品说明书以PDF格式发布,适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开,先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能,再给出完整安装步骤&…

2026/11/10 12:51:50 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历:翻开源码注释、论文摘要或者一份专业报告,每个字都认识,连在一起却像天书。想找人聊聊,身边要么没人懂,要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型,几秒钟之后&a…

2026/11/10 23:32:10 阅读更多 →

日新闻

周新闻

月新闻