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

Python 中的 `__dict__` 与 `__slots__` 深度解析

一、对象属性存储的本质Python 是一门动态语言每个对象的属性默认存储在一个字典中——这就是__dict__。这种设计赋予了 Python 极大的灵活性但也带来了内存和性能上的代价。__slots__则是 Python 提供的一种优化机制用固定的描述符替代字典存储。二、__dict__详解2.1 工作原理每个普通 Python 对象都拥有一个__dict__属性它是一个标准字典存储实例的所有属性classUser:def__init__(self,name,age):self.namename self.ageage uUser(Alice,30)print(u.__dict__)# {name: Alice, age: 30}属性的读写本质上是字典操作u.emailaliceexample.com# 等价于 u.__dict__[email] ...print(u.__dict__)# {name: Alice, age: 30, email: aliceexample.com}2.2 类的__dict__vs 实例的__dict__classAnimal:speciesUnknown# 类属性存储在 Animal.__dict__def__init__(self,name):self.namename# 实例属性存储在 self.__dict__aAnimal(Cat)print(Animal.__dict__)# mappingproxy({species: Unknown, __init__: function ..., ...})print(a.__dict__)# {name: Cat}类的__dict__是一个mappingproxy只读视图存储类方法、类属性和描述符实例的__dict__是普通dict。2.3 属性查找链MRO当访问obj.attr时Python 按如下顺序查找type(obj).__mro__中各类的__dict__里是否有数据描述符定义了__get__和__set__obj.__dict__中是否有该属性type(obj).__mro__中各类的__dict__里是否有非数据描述符或普通属性2.4 内存开销每个实例的__dict__是一个完整的dict对象。在 CPython 3.3 中引入了Key-Sharing DictionaryPEP 412优化同一类的实例如果在__init__中以相同顺序创建相同属性则共享 key 数组仅存储 values 数组。即便如此每个dict对象本身仍有 ~56 字节的固定开销CPython 3.11 64位加上哈希表预分配的容量。当你有百万级实例时这非常可观。三、__slots__详解3.1 基本用法classPoint:__slots__(x,y)def__init__(self,x,y):self.xx self.yy pPoint(1,2)print(p.x)# 1p.z3# AttributeError: Point object has no attribute zprint(hasattr(p,__dict__))# False定义__slots__后实例不再拥有__dict__属性以固定偏移量存储在对象结构体中不能动态添加未声明的属性3.2 底层实现当类定义了__slots__Python 为每个 slot 名称在类上创建一个member descriptor类似propertyprint(Point.x)# member x of Point objectsprint(type(Point.x))# class member_descriptor这些描述符直接通过 C 级别的固定偏移量tp_members读写对象内存无需哈希计算速度比字典查找更快。3.3 内存对比importsysclassDictPoint:def__init__(self,x,y):self.xx self.yyclassSlotPoint:__slots__(x,y)def__init__(self,x,y):self.xx self.yy dDictPoint(1,2)sSlotPoint(1,2)print(sys.getsizeof(d)sys.getsizeof(d.__dict__))# ~152 bytes (CPython 3.11)print(sys.getsizeof(s))# ~48 bytes节省约 60-70% 的内存。对于大规模数据对象如 ORM 行、科学计算粒子效果显著。3.4 性能优势属性访问基准测试CPython 3.11, 100M 次读取操作__dict____slots__提升读取属性~45ns~35ns~22%写入属性~55ns~40ns~27%提升幅度取决于 CPython 版本和内联缓存优化程度。在 3.12 的 specializing interpreter 下差距缩小但 slots 仍有优势。四、__slots__的继承规则4.1 父类无 slots子类有 slotsclassBase:pass# 有 __dict__classChild(Base):__slots__(x,)cChild()c.x1# 使用 slotc.y2# 仍然可以因为继承了 __dict__print(c.__dict__)# {y: 2}陷阱只要继承链中任何一个类没有__slots__实例就会有__dict__内存优化效果大打折扣。4.2 多层 slots 继承classA:__slots__(a,)classB(A):__slots__(b,)# 不要重复声明 abB()b.a1# 来自 A 的 slotb.b2# 来自 B 的 slot规则子类的__slots__只需声明新增的属性。重复声明会导致多个同名 descriptor虽然不报错但浪费内存。4.3 多重继承限制classX:__slots__(x,)classY:__slots__(y,)classZ(X,Y):# OK: 多个非空 slots 父类且无冲突的内存布局__slots__(z,)但如果多个父类定义了非空__slots__且存在非平凡的 C 级布局冲突会抛出TypeError。实践中的安全规则多重继承时最多一个父类有非空__slots__。五、__slots__与__dict__共存可以在__slots__中显式包含__dict__classHybrid:__slots__(x,__dict__)def__init__(self,x):self.xx# 走 slothHybrid(1)h.y2# 走 __dict__print(h.__dict__)# {y: 2}这样x享受 slot 的性能优势同时保留动态属性能力。适合核心属性固定但允许扩展的场景。六、__slots__与__weakref__默认情况下slots 类实例不支持弱引用importweakrefclassNoWeak:__slots__(x,)weakref.ref(NoWeak())# TypeError: cannot create weak referenceclassWithWeak:__slots__(x,__weakref__)weakref.ref(WithWeak())# OK如果需要弱引用支持必须在__slots__中包含__weakref__。七、实战场景与最佳实践7.1 何时使用__slots__场景推荐大量同质实例10k 对象✅ 强烈推荐数据传输对象DTO/VO✅ 推荐ORM 模型行⚠️ 视框架支持需要动态添加属性❌ 不适合需要__dict__做序列化⚠️ 需额外处理Mixin / 抽象基类❌ 通常不适合7.2 与 dataclasses 配合fromdataclassesimportdataclassdataclassclassVector3D:__slots__(x,y,z)x:floaty:floatz:floatPython 3.10 的dataclass支持slotsTrue参数自动处理dataclass(slotsTrue)classVector3D:x:floaty:floatz:float7.3 与 Pydantic 配合frompydanticimportBaseModelclassConfig(BaseModel):model_config{frozen:True}# Pydantic v2 内部使用 __slots__ 优化host:strport:intPydantic v2 的BaseModel已经在内部使用 slots 优化核心字段存储。7.4 序列化注意事项pickle默认依赖__dict__。对 slots 类需要实现__getstate__/__setstate__classSlotObj:__slots__(a,b)def__getstate__(self):return{slot:getattr(self,slot)forslotinself.__slots__ifhasattr(self,slot)}def__setstate__(self,state):forslot,valueinstate.items():setattr(self,slot,value)八、CPython 内部视角8.1 对象内存布局┌────────────────────────────────────┐ │ PyObject_HEAD (ob_refcnt, ob_type)│ 16 bytes ├────────────────────────────────────┤ │ __dict__ pointer │ 8 bytes (无 slots 时) │ __weakref__ pointer │ 8 bytes (无 slots 时) ├────────────────────────────────────┤ │ slot_0 (PyObject*) │ 8 bytes (有 slots 时) │ slot_1 (PyObject*) │ 8 bytes │ ... │ └────────────────────────────────────┘使用__slots__时属性直接作为PyObject*指针紧凑排列在对象体内消除了字典的哈希表、key 数组和间接寻址开销。8.2 Key-Sharing Dict (PEP 412)CPython 3.3 对同一类型的实例__dict__做了优化Instance A.__dict__ ──┐ Instance B.__dict__ ──┼──► Shared Keys Array: [name, age, email] Instance C.__dict__ ──┘ Values A: [ptr, ptr, ptr] Values B: [ptr, ptr, ptr] Values C: [ptr, ptr, ptr]这减少了内存使用但仍无法与__slots__的紧凑布局相比因为每个实例仍需一个dict对象头和 values 数组。九、常见陷阱9.1 默认可变值classWrong:__slots__(items,)items[]# 类属性会与 slot descriptor 冲突# 正确做法在 __init__ 中赋值classRight:__slots__(items,)def__init__(self):self.items[]9.2 忘记在子类重声明__slots__classParent:__slots__(x,)classChild(Parent):pass# 没有 __slots__Child 实例会获得 __dict__失去优化9.3 与元类/装饰器冲突某些框架的元类会操作__dict__使用__slots__时需验证兼容性。例如早期 SQLAlchemy 的 declarative base 与__slots__不兼容。十、总结对比特性__dict____slots__内存占用较高~104-152 bytes/实例较低~48-64 bytes/实例属性访问速度哈希查找固定偏移量动态添加属性✅❌除非包含__dict__弱引用支持✅ 默认需显式声明__weakref__继承复杂度低高需每层声明序列化兼容✅ 天然支持需额外实现适用场景通用、灵活大量实例、性能敏感核心原则__dict__是 Python 动态性的基石适合绝大多数场景__slots__是有针对性的优化手段在明确需要节省内存或提升属性访问性能时启用。不要过早优化——先 profile再决定是否引入__slots__。

相关文章:

Python 中的 `__dict__` 与 `__slots__` 深度解析

一、对象属性存储的本质 Python 是一门动态语言,每个对象的属性默认存储在一个字典中——这就是 __dict__。这种设计赋予了 Python 极大的灵活性,但也带来了内存和性能上的代价。__slots__ 则是 Python 提供的一种优化机制,用固定的描述符替代…...

ChatLLM:本地化大语言模型应用开发框架的设计与实战

1. 项目概述:一个面向开发者的本地化大语言模型应用框架最近在折腾本地部署大语言模型(LLM)的朋友,估计都绕不开一个核心痛点:模型本身有了,但怎么把它变成一个真正好用、能集成到自己项目里的服务&#xf…...

基于.NET的Discord机器人框架WMagicBotR:模块化设计与异步编程实践

1. 项目概述:一个面向Discord的现代化机器人框架如果你在Discord社区里泡过一段时间,无论是管理一个游戏公会、一个技术讨论组,还是一个兴趣社群,你大概率会接触过形形色色的机器人。它们能自动欢迎新成员、管理聊天内容、播放音乐…...

英雄联盟专业录像编辑器:免费开源工具League Director完全指南

英雄联盟专业录像编辑器:免费开源工具League Director完全指南 【免费下载链接】leaguedirector League Director is a tool for staging and recording videos from League of Legends replays 项目地址: https://gitcode.com/gh_mirrors/le/leaguedirector …...

如何自定义pagefacade的数据转换逻辑?go语言

在 UiSimpleQR 框架中,pagefacade 的核心职责是将数据库实体(Entity)转换为响应对象(Response)。默认情况下,它可能只是简单的字段映射或类型断言。如果你想自定义转换逻辑(例如:字段…...

如何用ncmdumpGUI三分钟解锁网易云音乐NCM格式:Windows用户必备的音乐文件转换终极指南

如何用ncmdumpGUI三分钟解锁网易云音乐NCM格式:Windows用户必备的音乐文件转换终极指南 【免费下载链接】ncmdumpGUI C#版本网易云音乐ncm文件格式转换,Windows图形界面版本 项目地址: https://gitcode.com/gh_mirrors/nc/ncmdumpGUI 你是否曾在…...

2分钟搞定Windows苹果驱动安装:智能脚本解决iPhone连接难题

2分钟搞定Windows苹果驱动安装:智能脚本解决iPhone连接难题 【免费下载链接】Apple-Mobile-Drivers-Installer Powershell script to easily install Apple USB and Mobile Device Ethernet (USB Tethering) drivers on Windows! 项目地址: https://gitcode.com/g…...

告别低效重复:ChatGPT 5.5 + GPT Image 2 重塑开发者工作流

摘要: 在 2026 年的今天,开发者的工作流正在经历一场静默的革命。本文将通过实测案例,展示如何利用 ChatGPT 5.5 的代码理解能力与 GPT Image 2 的视觉生成能力,结合 VS Code 插件与 API 调用,实现从架构设计、代码生成…...

Windows 11中文输入法失效与Edge卸载难题的精准修复方案

1. 项目概述与核心痛点解析如果你是一名长期在Windows 11环境下工作的开发者或文字工作者,特别是习惯使用VS Code、Cursor这类基于Chromium的编辑器,或者深度依赖命令行工具,那么你很可能遭遇过一个令人抓狂的问题:在特定的输入框…...

代码注释对于新手及团队的重要性

今天小编与大家一起来讨论代码中的注释对新手、团队的不同作用,这里做一个总结。对于新手帮助理解代码逻辑:有注释的代码能让新手更快的上手,理解代码的各个功能和实现原理,避免学习过程中多走弯路。提高代码可读性:有…...

如何快速上手YuukiPS启动器:原神玩家的终极智能启动解决方案

如何快速上手YuukiPS启动器:原神玩家的终极智能启动解决方案 【免费下载链接】Launcher-PC 项目地址: https://gitcode.com/gh_mirrors/la/Launcher-PC 还在为原神多账号管理和版本切换而烦恼吗?今天我要为你介绍一款专为原神玩家设计的免费开源…...

Lumafly:空洞骑士模组管理终极指南 - 跨平台一键管理300+模组

Lumafly:空洞骑士模组管理终极指南 - 跨平台一键管理300模组 【免费下载链接】Lumafly A cross platform mod manager for Hollow Knight written in Avalonia. 项目地址: https://gitcode.com/gh_mirrors/lu/Lumafly 在《空洞骑士》的深邃世界中&#xff0…...

用ESP32向OneNET上报传感器数据:一个完整的温湿度监测项目从硬件到云端

ESP32与OneNET构建智能温湿度监测系统:从硬件部署到云端可视化的全链路实践 在智能家居、农业大棚或仓储管理等场景中,环境温湿度数据的实时监测与记录往往是最基础却关键的物联网应用。ESP32作为一款兼具Wi-Fi/蓝牙功能且性价比极高的微控制器&#xf…...

告别手动建模!用EPLAN P8导入STEP文件,5分钟搞定威图机柜3D模型

告别手动建模!用EPLAN P8导入STEP文件,5分钟搞定威图机柜3D模型 在电气工程设计领域,时间就是竞争力。传统手动创建机柜3D模型的过程往往需要数小时甚至更长时间,从基础框架搭建到每个安装板的精确定位,工程师们不得不…...

QtScrcpy:终极跨平台Android投屏控制软件完全指南

QtScrcpy:终极跨平台Android投屏控制软件完全指南 【免费下载链接】QtScrcpy Android real-time display control software 项目地址: https://gitcode.com/GitHub_Trending/qt/QtScrcpy 在当今多设备协同工作的时代,如何高效地将Android手机屏幕…...

别再只刷新了!手把手教你排查Nginx/Apache/IIS网关超时504错误的5个实战场景

网关超时504错误深度排查:Nginx/Apache/IIS实战指南 当你深夜收到服务器告警短信,打开监控看到一片刺眼的504状态码时,那种头皮发麻的感觉我太熟悉了。作为经历过数百次网关超时战役的老兵,我想分享的不是教科书式的定义&#xf…...

Android Framework开发深度解析与面试指南

引言 Android Framework是Android系统的核心层,负责管理应用生命周期、资源分配和硬件交互。它为上层应用提供基础服务,如Activity管理、Binder IPC和内存回收。在物联网时代,Framework优化对设备性能至关重要。本文将深入探讨Framework核心机制,并提供实用面试指南,帮助…...

ESPTool完整指南:5个简单步骤掌握ESP芯片烧录终极技巧

ESPTool完整指南:5个简单步骤掌握ESP芯片烧录终极技巧 【免费下载链接】esptool Serial utility for flashing, provisioning, and interacting with Espressif SoCs 项目地址: https://gitcode.com/gh_mirrors/es/esptool 想要快速上手ESP8266、ESP32等物联…...

Android框架层深入解析与面试指南

本文基于Android开发工程师职位描述,聚焦于Android框架层(Framework Layer)的核心内容。Framework层是Android系统的核心骨架,负责管理应用生命周期、资源分配、进程间通信等关键功能。职位描述中强调的AMS(Activity Manager Service)、PMS(Package Manager Service)、…...

Android无线技术深度解析:蓝牙、WiFi与NFC开发实践与面试指南

在移动互联网时代,蓝牙、WiFi和NFC作为核心无线技术,已成为Android系统开发的关键领域。本文基于Android开发工程师(无线技术方向)的职责要求,深入探讨这些技术的实现原理、开发挑战、优化方法,并附有面试常见问题与答案。文章旨在帮助开发者提升实战能力,内容涵盖源码级…...

告别Win32DiskImager:用dd命令在Ubuntu下给开发板烧录U-Boot的保姆级教程

告别Win32DiskImager:用dd命令在Ubuntu下给开发板烧录U-Boot的保姆级教程 在嵌入式开发的世界里,U-Boot就像是一把万能钥匙,没有它,再强大的开发板也无法启动。传统上,很多开发者习惯在Windows环境下使用Win32DiskImag…...

AI Agent技能工具箱:模块化设计、核心技能与实战应用

1. 项目概述:一个面向AI智能体的技能工具箱 最近在折腾AI智能体(AI Agent)的开发,发现一个挺有意思的现象:很多开发者,包括我自己在内,在初期都会把大量精力花在“重复造轮子”上。比如&#xf…...

MATLAB实战:用Ellip函数设计IIR滤波器,分离三路混叠的调幅信号

MATLAB实战:用Ellip函数设计IIR滤波器分离三路混叠调幅信号 想象一下,你面前有一锅香气扑鼻的浓汤,三种不同的食材——胡萝卜、土豆和洋葱——已经完全炖烂混在一起。现在,你需要用三个不同的筛子,分别把每种食材的颗…...

Applite:3分钟掌握macOS应用管理,告别复杂命令行的终极指南

Applite:3分钟掌握macOS应用管理,告别复杂命令行的终极指南 【免费下载链接】Applite User-friendly GUI macOS application for Homebrew Casks 项目地址: https://gitcode.com/gh_mirrors/ap/Applite 还在为macOS应用安装和管理而头疼吗&#x…...

MCP服务器:将OpenAPI目录转化为AI可查询的实时知识库

1. 项目概述:当开放API目录遇上MCP如果你和我一样,经常需要和各种各样的API打交道,那你肯定体会过那种“信息过载”的烦恼。GitHub上有个宝藏仓库叫openapi-directory,它收集了海量的OpenAPI规范文件,覆盖了从天气、支…...

追踪月度账单明细以分析各模型项目的成本构成

追踪月度账单明细以分析各模型项目的成本构成 1. 账单功能入口与基础视图 Taotoken控制台的「账单与用量」模块提供了完整的消费记录追溯能力。登录后,在左侧导航栏点击「账单」即可进入月度账单概览页。默认视图会展示当前月份的消费总额、总Token消耗量以及按模…...

Mantou:基于任务组合的轻量级前端构建工具实践指南

1. 项目概述:一个轻量级、模块化的前端构建工具最近在重构一个老项目的前端部分,面对一堆零散的JS、CSS文件,还有各种需要压缩、打包、转译的任务,感觉构建流程像一团乱麻。用Webpack吧,配置复杂得像天书,为…...

MacType字体渲染终极指南:让Windows文字显示如macOS般清晰锐利

MacType字体渲染终极指南:让Windows文字显示如macOS般清晰锐利 【免费下载链接】mactype Better font rendering for Windows. 项目地址: https://gitcode.com/gh_mirrors/ma/mactype 还在为Windows系统下模糊的字体显示效果而烦恼吗?作为追求极致…...

WarcraftHelper终极指南:如何在现代电脑上完美运行魔兽争霸3

WarcraftHelper终极指南:如何在现代电脑上完美运行魔兽争霸3 【免费下载链接】WarcraftHelper Warcraft III Helper , support 1.20e, 1.24e, 1.26a, 1.27a, 1.27b 项目地址: https://gitcode.com/gh_mirrors/wa/WarcraftHelper 还在为魔兽争霸3在现代电脑上…...

如何彻底解决腾讯游戏ACE-Guard卡顿问题:终极性能优化指南

如何彻底解决腾讯游戏ACE-Guard卡顿问题:终极性能优化指南 【免费下载链接】sguard_limit 限制ACE-Guard Client EXE占用系统资源,支持各种腾讯游戏 项目地址: https://gitcode.com/gh_mirrors/sg/sguard_limit 你是否在玩《英雄联盟》、《穿越火…...