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

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

  • [Bilibili 同步视频](#Bilibili 同步视频)
  • 一、先搭舞台:一个简单的继承示例
  • [二、`dict`:对象属性的 "存储字典"](#二、__dict__:对象属性的 “存储字典”)
    • [1. 底层核心:高性能的内置数据结构](#1. 底层核心:高性能的内置数据结构)
    • [2. 实例的 `dict`:只存自身实例属性](#2. 实例的 __dict__:只存自身实例属性)
    • [3. 类的 `dict`:包含完整类信息](#3. 类的 __dict__:包含完整类信息)
    • [4. 动态操控:直接修改 `dict` 增删属性](#4. 动态操控:直接修改 __dict__ 增删属性)
  • [三、`dir()`:对象全貌的 "属性清单"](#三、dir():对象全貌的 “属性清单”)
    • [1. 核心用法:一键获取全量属性](#1. 核心用法:一键获取全量属性)
    • [2. `dir()` 与 `dict` 的关键区别](#2. dir()__dict__ 的关键区别)
    • [3. 兼容无 `dict` 的内置对象](#3. 兼容无 __dict__ 的内置对象)
  • [四、总结:用好自省,吃透 Python 对象](#四、总结:用好自省,吃透 Python 对象)

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

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


Bilibili 同步视频

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


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

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

python 复制代码
# 定义父类 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__,我们会发现:

python 复制代码
print(user.__dict__)
# 输出:{'school_name': '慕课网'}

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

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

python 复制代码
print(user.name)  # 输出:user

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

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

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

python 复制代码
print(Person.__dict__)

输出会包含:

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

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

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

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

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


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

如果说 __dict__属性账本 ,那 dir() 就是全量目录 📋。

dir() 是 Python 内置的自省函数,功能比 __dict__ 更强大,能列出对象所有可用属性与方法(含继承的、内置的魔法方法)。

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

python 复制代码
# 查看 Student 实例的所有属性
print(dir(user))

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

2. dir()__dict__ 的关键区别

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

3. 兼容无 __dict__ 的内置对象

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

python 复制代码
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 面向对象的另一核心:super()**** 函数,彻底理清继承中的方法调用逻辑~