Python中没有__dict__属性的类型
已于 2025年10月12日 16:54 修改
访问次数:0
这个问题看似简单,其实涉及到 Python 对象模型(Object Model) 的核心机制。
我们来系统讲一下:哪些对象有 __dict__,哪些没有,以及为什么。
🧩 一、__dict__ 是什么?
__dict__ 是一个字典属性,用来存放对象的可写实例属性(attribute storage)。
也就是说:
- 当你对一个对象执行 self.x = 10 时,Python 默认会把这个属性存进对象的 __dict__ 中;
- 这样以后访问 self.x 时,就能在 __dict__ 里找到。
🧩 二、哪些对象有 __dict__
| 类型 | 是否有 __dict__ | 原因 / 说明 |
|---|---|---|
| ✅ 用户自定义类的实例 | ✅ 有 | 默认每个实例都有一个可写的 __dict__ 来存属性 |
| ✅ 大多数自定义类(非内建类型) | ✅ 有 | 除非用 __slots__ 禁用了 |
| ⚙️ 类对象本身 | ✅ 有 | 存放类属性和方法 |
| ⚙️ 模块对象 | ✅ 有 | 存放模块的变量(即全局命名空间) |
示例👇
class A:
def __init__(self):
self.x = 1
a = A()
print(a.__dict__) # {'x': 1}
print(A.__dict__) # 类对象的属性(方法、静态变量等)
🧩 三、哪些对象 没有 __dict__
| 类型 | 是否有 __dict__ | 说明 |
|---|---|---|
❌ 内建类型实例(如 int, list, tuple, dict, str, set) | ❌ 没有 | 这些类型是用 C 实现的,结构固定,不需要动态存属性 |
❌ 使用 __slots__ 限制属性的类实例 | ❌ 没有 | 禁用了默认的 __dict__ 存储机制 |
示例👇
x = 10
print(hasattr(x, "__dict__")) # False
lst = [1, 2, 3]
print(hasattr(lst, "__dict__")) # False
d = {"a": 1}
print(hasattr(d, "__dict__")) # False
🧩 四、为什么内建类型没有 __dict__
因为:
- 性能考虑: 内建类型(int、list、dict 等)是由 C 实现的,数据结构是固定的。 不需要也不允许动态添加属性。
- 内存占用: 如果每个 int 都有一个 __dict__,那内存会爆炸。
- 一致性与安全性: 内建类型通常有严格的行为定义,允许用户随意加属性会破坏设计。
🧩 五、可以给内建类型“加属性”吗?
默认不行:
x = 10
x.new_attr = "hi" # ❌ AttributeError: 'int' object has no attribute 'new_attr'
但你可以“包装”它:
class MyInt(int):
pass
m = MyInt(5)
m.extra = "hello"
print(m.__dict__) # {'extra': 'hello'}
✅ 自定义子类实例就有 __dict__,因为它走了普通对象的存储机制。
🧩 六、__slots__ 特殊情况
如果你在类中定义了 __slots__,就会关闭默认的 __dict__:
class B:
__slots__ = ("x", "y")
b = B()
b.x = 1
print(hasattr(b, "__dict__")) # False
__slots__ 告诉 Python:
“我只会用这几个固定的属性,不需要动态字典了。”
从而节省内存,加快访问速度。
✅ 七、总结表格
| 类型 | 是否有 __dict__ | 可动态加属性? | 说明 |
|---|---|---|---|
| 用户自定义类实例 | ✅ 有 | ✅ 可以 | 属性存储在 __dict__ |
使用 __slots__ 的类实例 | ❌ 无 | ❌ 不可以(除非定义 __dict__ 槽) | 限定属性集合 |
内建类型实例(int, list, dict 等) | ❌ 无 | ❌ 不可以 | 结构固定,C 实现 |
| 类对象本身 | ✅ 有 | ✅ 可以 | 存放方法和类属性 |
| 模块对象 | ✅ 有 | ✅ 可以 | 存放模块全局变量 |
📌 一句话记忆:
✅ “普通对象有 __dict__ 存属性, ❌ 内建类型没有 __dict__(它们的结构是写死的)。”
评论(0)