Python中没有__dict__属性的类型


这个问题看似简单,其实涉及到 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__

因为:

  1. 性能考虑: 内建类型(int、list、dict 等)是由 C 实现的,数据结构是固定的。 不需要也不允许动态添加属性。
  2. 内存占用: 如果每个 int 都有一个 __dict__,那内存会爆炸。
  3. 一致性与安全性: 内建类型通常有严格的行为定义,允许用户随意加属性会破坏设计。


🧩 五、可以给内建类型“加属性”吗?

默认不行:

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)