Python:实例 __dict__ 详解

在 Python 的对象模型中,实例的属性并不是直接存在于对象内部的字段,而是统一存放在一个名为 dict 的映射结构中。

理解实例 dict,本质上是在理解实例属性从何而来、属性如何被创建、查找与销毁以及实例命名空间的生命周期与作用边界。

一、实例 dict 的定义与本质

实例 dict 是一个字典对象,用于存储实例对象的"实例级属性"。

perl 复制代码
class A:    pass
a = A()a.x = 10
print(a.__dict__)    # {'x': 10}type(a.__dict__)     # <class 'dict'>

说明:

• a.dict 是实例命名空间(Instance Namespace)。

• 键是属性名(字符串),值是对应的属性值。

每个实例都有自己独立的 dict。因此:

apache 复制代码
a1 = A()a2 = A()
a1.x = 1a2.x = 2
print(a1.__dict__)    # {'x': 1}print(a2.__dict__)    # {'x': 2}

实例之间不会共享 dict

二、实例属性的创建机制:写入即绑定

实例属性并不需要提前声明。任何对实例属性的赋值操作,都会直接写入实例的 dict

ini 复制代码
a.y = 20

等价于:

javascript 复制代码
a.__dict__['y'] = 20

这说明,Python 中实例属性是运行期动态绑定的。实例 dict 是属性创建的唯一存储位置(不考虑 slots 时)。

删除属性时同理:

css 复制代码
del a.y# 等价于del a.__dict__['y']

三、实例 dict 在属性查找中的位置

当访问 a.attr 时,Python 使用以下固定顺序进行查找(简化版):

1、实例 a.dict

2、类 A.dict

3、父类的 dict(按 MRO 顺序)

4、若仍未找到,触发 getattr()

因此,实例 dict 具有非常高的优先级。

示例:

python 复制代码
class A:    x = 100    # 类属性
a = A()a.x = 10       # 实例属性
print(a.x)     # 10print(A.x)     # 100

原因是:

ini 复制代码
a.__dict__ == {'x': 10}

实例属性会遮蔽(shadow)同名类属性。

四、实例 dict 的生命周期

实例 dict 的生命周期与实例对象完全一致。

1、创建时

ini 复制代码
a = A()

此时:

ini 复制代码
a.__dict__ == {}

实例创建完成后即拥有一个空的 dict

2、使用期间

随着属性赋值、修改、删除,实例 dict 持续变化:

apache 复制代码
a.x = 1a.y = 2del a.x

3、销毁时

当实例对象被垃圾回收:

css 复制代码
del a

实例 dict 随实例一并销毁,不会留下任何"残余属性"。

因此,实例 dict 不具备跨实例、跨生命周期的持久性。

五、实例 dict 与方法、描述符的关系

1、实例方法不存放在实例 dict

python 复制代码
class A:    def f(self): pass
a = A()'a.f' in a.__dict__     # False

说明:

方法定义在类体内,存放于类 dict(此处为 A.dict)中,通过描述符机制动态绑定。

2、数据描述符优先级高于实例 dict

对于数据描述符(比如 property):

ruby 复制代码
class A:    @property    def x(self):        return 42
a = A()a.__dict__['x'] = 100
a.x   # 42

说明:

数据描述符优先于实例 dict,但非数据描述符优先级要低于实例 dict

六、实例 dictslots 的限制关系

如果类定义了slots

kotlin 复制代码
class A:    __slots__ = ('x',)
a = A()a.x = 1

此时:

python 复制代码
hasattr(a, '__dict__')   # False(默认)

说明:

slots 会移除实例 dict,实例属性改为使用静态结构存储,从根本上改变了实例命名空间模型。

若要显式保留:

kotlin 复制代码
class A:    __slots__ = ('x', '__dict__')

七、常见误解与澄清

误解 1:实例属性存放在类中

❌ 错误

✔ 正解:实例属性只存放在实例 dict 中。

误解 2:实例 dict 与类 dict 是同一个

❌ 错误

✔ 正解:它们是完全不同的命名空间。

误解 3:方法属于实例

❌ 错误

✔ 正解:方法属于类,通过描述符机制绑定实例。

误解 4:删除实例不会影响类属性

✔ 正确

实例 dict 的生命周期与类完全无关。

📘 小结

实例 dict 是实例级命名空间,用于存储对象在运行期动态绑定的属性。它以字典形式存在,生命周期与实例一致,在属性查找顺序中通常优先于类 dict。实例属性的赋值、修改与删除本质上都是对实例 dict 的操作。方法不存放在实例 dict 中,而是定义在类中并通过描述符机制动态绑定。

理解实例 dict 有助于掌握 Python 的属性模型、命名空间体系与对象生命周期管理。

"点赞有美意,赞赏是鼓励"

相关推荐
程序员榴莲几秒前
网络编程入门 Python Socket 实现一个简单的用户认证系统
服务器·网络·python
kyriewen几秒前
我用AI把公司10万行代码屎山重构了,CTO看了代码后说:你提前转正
前端·javascript·ai编程
SelectDB技术团队1 分钟前
PB 级自动驾驶数据秒级检索:Apache Doris 统一多模态数据平台实践
数据库·人工智能·自动驾驶·apache doris·selectdb
ttwuai3 分钟前
XYGo Admin 菜单与路由:Vue3 动态路由 + GoFrame 权限菜单的完整实现方案
前端·vue·后台框架
BIG_PEI7 分钟前
检查并安装Redis
java
知识分享小能手9 分钟前
Flask入门学习教程,从入门到精通, 认识Flask路由 — 知识点详解 (2)
python·学习·flask
AI棒棒牛9 分钟前
YOLO26改进创新 | 全网首发!VECA弹性核心注意力重塑全局建模,线性复杂度增强检测骨干,嘎嘎创新!
python·yolo·目标检测·yolo26·主干改进
大貔貅喝啤酒9 分钟前
基于Windows下载安装Android Studio 3.3.2版本教程(2026详细图文版)
android·java·windows·android studio
奋斗的小方11 分钟前
Java基础篇09:项目实战
java·开发语言
程序员码歌11 分钟前
OpenSpec 到 Superpowers:AI 编码从说清到做对
android·前端·人工智能