Python 高级编程 021:`__dict__`与`dir`的深度解析

0 阅读4分钟

在 Python 面向对象的世界里,自省(Introspection) 是一项极具魅力的核心能力 —— 它让我们能在程序运行时,主动探查对象的类型、属性、方法与内部结构,就像拥有一双 “透视眼”,穿透封装,看清对象的本质。

今天,我们就聚焦 Python 自省最常用的两大神兵:__dict__**** 属性dir()** 内置函数**,从继承案例入手,彻底搞懂它们的用法、区别与底层逻辑✨。


Bilibili 同步视频

Python 高级编程 021:__dict__dir()的深度解析


一、先搭舞台:一个简单的继承示例

为了清晰演示自省机制,我们先定义一组具有继承关系的类,这是后续所有操作的基础👇

# 定义父类 Person
class Person:
    """人:基础父类"""
    name = "user"  # 类属性

# 定义子类 Student,继承自 Person
class Student(Person):
    """学生:继承 Person,扩展自有属性"""
    def __init__(self):
        self.school_name = "慕课网"  # 实例属性

# 实例化 Student 对象
user = Student()

这里的层级关系很清晰: Student → 继承 Person → 实例化为 userPerson 的类属性 nameStudent 的实例属性 school_name 共同构成了对象的属性体系。


二、__dict__:对象属性的 “存储字典”

1. 底层核心:高性能的内置数据结构

CPython 编译器 中,__dict__纯 C 语言实现的字典,经过了极致优化,是 Python 性能最高的数据结构之一🔥。 Python 类与实例的所有属性,本质上都通过 __dict__ 来存储和管理 —— 它就是对象属性的 “专属账本”。

2. 实例的 __dict__:只存自身实例属性

直接打印实例 user__dict__,我们会发现:

print(user.__dict__)
# 输出:{'school_name': '慕课网'}

只包含实例自身初始化的属性,并没有父类 Personname 属性!

但神奇的是,直接访问 user.name 依然能得到结果:

print(user.name)  # 输出:user

这是 Python 的 MRO(方法解析顺序) 在起作用:访问属性时,Python 会沿继承链向上查找name 是父类 Person类属性,不属于子类实例,因此不会出现在实例的 __dict__ 中。

3. 类的 __dict__:包含完整类信息

类本身也是对象,它的 __dict__ 远比实例丰富,包含模块、类名、文档、弱引用、类属性等全部信息:

print(Person.__dict__)

输出会包含: __module__(所属模块)、name(类属性)、__doc__(类文档)、__dict__(自身引用)、__weakref__(弱引用)等完整元信息。

4. 动态操控:直接修改 __dict__ 增删属性

__dict__ 不仅能查看,还能直接读写,实现对象属性的动态操控:

# 动态添加实例属性
user.__dict__["school_addr"] = "北京市"
# 直接访问新属性
print(user.school_addr)  # 输出:北京市

这就是 __dict__ 的强大之处 —— 直接操作对象的属性存储字典,灵活掌控对象状态。


三、dir():对象全貌的 “属性清单”

如果说 __dict__属性账本,那 dir() 就是全量目录📋。 dir() 是 Python 内置的自省函数,功能比 __dict__ 更强大,能列出对象所有可用属性与方法(含继承的、内置的魔法方法)。

1. 核心用法:一键获取全量属性

# 查看 Student 实例的所有属性
print(dir(user))

执行后会输出一长串列表,不仅有 school_namename,还有 Python 内置的 __init____str____class__ 等魔法方法,覆盖对象的全部可用成员

2. dir()__dict__ 的关键区别

特性__dict__dir()
内容仅对象自身存储的属性 + 对应值对象所有可用属性 / 方法名(含继承、内置)
格式字典(键值对)列表(仅名称)
适用场景查看 / 修改自有属性、动态操控快速探查对象全貌、确认支持的方法

3. 兼容无 __dict__ 的内置对象

很多 Python 内置类型(如 liststr没有 ****__dict__,直接访问会抛异常,但 dir() 依然能完美工作:

a = [1, 2, 3]
# print(a.__dict__)  # 报错:AttributeError
print(dir(a))  # 正常输出 list 的所有方法与属性

这让 dir() 成为探查所有 Python 对象的通用工具,尤其适合查看内置类型实现的魔法函数。


四、总结:用好自省,吃透 Python 对象

  1. 自省是什么:运行时探查对象内部结构的能力,是 Python 动态语言的核心特性;

  2. __dict__:C 语言实现的高性能属性字典,存自身属性 + 值,支持动态操控,类与实例都有;

  3. dir():全量属性清单,列所有可用成员,无值、兼容所有对象,适合快速探查;

  4. 属性查找:实例无属性时,Python 会通过 MRO 沿继承链向上查找,父类属性不属于实例本身。

掌握 __dict__dir(),就等于掌握了 Python 对象的透视密码,无论是调试、源码阅读还是动态编程,都能事半功倍🚀。

Python 高级编程 021:__dict__与dir()的深度解析

下一节,我们将继续探索 Python 面向对象的另一核心:super()**** 函数,彻底理清继承中的方法调用逻辑~