全部学科
Python全栈
python
NodeJS全栈
nodejs
小程序首页
📅 2026-05-19 10 分钟 ✍️ juanwangdev

Python对象模型

Python中一切皆对象,所有对象共享统一的底层结构。理解对象模型是深入Python内部机制的基础。

PyObject 结构

每个Python对象在C层面都始于PyObject头:

C
// C层面的定义(简化)
typedef struct _object {
    Py_ssize_t ob_refcnt;      // 引用计数
    PyTypeObject *ob_type;     // 类型指针
} PyObject;

// 带变长数据的对象
typedef struct {
    PyObject ob_base;          // 对象头
    Py_ssize_t ob_size;        // 元素数量
} PyVarObject;

在Python中观察:

Python
import sys

# 引用计数
x = []
print(sys.getrefcount(x))  # 至少为2(x变量 + getrefcount参数)

# 对象大小
print(sys.getsizeof(x))     # 列表对象本身的大小
print(sys.getsizeof(1))     # 整数对象大小

# 类型对象
print(type(x))              # <class 'list'>
print(type(type(x)))        # <class 'type'>

对象头与内存布局

Python
import sys

# 整数对象结构
# PyObject_HEAD (16字节: refcnt + type_ptr)
# ob_digit (变长,存储数值)
n = 12345678901234567890
print(f"整数大小: {sys.getsizeof(n)} 字节")

# 列表对象结构
# PyObject_HEAD (16字节)
# ob_size (8字节,元素数量)
# allocated (8字节,已分配空间)
# items[] (指针数组)
lst = [1, 2, 3]
print(f"列表大小: {sys.getsizeof(lst)} 字节")  # 不含元素

# 字符串对象结构
# PyObject_HEAD
# length (8字节)
# hash (-1或缓存值)
# state (1字节)
# UTF-8 length或ASCII标记
# data[]
s = "hello"
print(f"字符串大小: {sys.getsizeof(s)} 字节")

类型对象 PyTypeObject

类型也是对象,其结构定义了对象的行为:

Python
# 类型对象的属性
class MyClass:
    "示例类"
    attr = 123

    def method(self):
        pass

# 类型属性
print(MyClass.__name__)        # 'MyClass'
print(MyClass.__doc__)         # '示例类'
print(MyClass.__dict__)        # 命名空间映射
print(MyClass.__bases__)       # (<class 'object'>,)
print(MyClass.__mro__)         # 方法解析顺序
print(MyClass.__module__)      # 定义模块

# 特殊属性
print(int.__itemsize__)        # 元素大小(定长类型为0)
print(int.__basicsize__)       # 基础大小
print(list.__itemsize__)       # 每个元素指针大小

类型槽位(Slots)

类型对象通过槽位定义行为:

Python
# 查看类型的槽位映射
class Counter:
    def __init__(self, start=0):
        self.value = start

    def __add__(self, other):
        return Counter(self.value + other)

    def __repr__(self):
        return f"Counter({self.value})"

    def __int__(self):
        return self.value

c = Counter(10)
c2 = c + 5
print(c2)           # Counter(15)
print(int(c2))      # 15

# 对应的槽位(C层面)
# nb_add -> __add__
# tp_repr -> __repr__
# nb_int -> __int__

常用槽位对应:

槽位族特殊方法说明
tp_new__new__对象创建
tp_init__init__对象初始化
tp_repr__repr__字符串表示
tp_hash__hash__哈希值
tp_call__call__可调用
tp_getattr__getattr__属性获取
tp_setattr__setattr__属性设置
tp_iter__iter__迭代器
tp_iternext__next__下一个元素
nb_add__add__加法
sq_length__len__长度
mp_subscript__getitem__索引访问

type 作为元类

type既是类型,也是元类:

Python
# type 的双重身份
print(type(1))         # <class 'int'>
print(type(int))       # <class 'type'>
print(type(type))      # <class 'type'> - type是自身的实例

# 使用 type 动态创建类
MyClass = type(
    'MyClass',
    (object,),
    {'attr': 123, 'method': lambda self: 'hello'}
)

obj = MyClass()
print(obj.attr)        # 123
print(obj.method())    # 'hello'

对象的身份与相等

Python
a = [1, 2, 3]
b = [1, 2, 3]
c = a

# 身份(内存地址)
print(id(a))           # 对象的唯一标识
print(id(b))            # 不同
print(id(c))            # 与a相同

# is 比较身份(比较id)
print(a is b)           # False
print(a is c)           # True

# == 比较值(调用 __eq__)
print(a == b)           # True

# 特殊情况:小整数缓存
print(256 is 256)       # True(小整数缓存)
print(257 is 257)       # 可能True(编译时常量折叠)
x, y = 257, 257
print(x is y)           # 可能False(运行时创建)

不可变对象的可变视图

Python
# 字符串底层是可变缓冲区
import sys

s = "hello"
# 字符串不可变,但可通过内存视图操作底层字节

# bytes 和 bytearray
b = bytes([1, 2, 3])       # 不可变
ba = bytearray([1, 2, 3])  # 可变
ba[0] = 10                  # 可修改

# memoryview 提供零拷贝视图
mv = memoryview(ba)
mv[1] = 20
print(ba)  # bytearray(b'\n\x14\x03')

要点总结

  1. PyObject头包含引用计数和类型指针,所有对象共享
  2. PyVarObject扩展用于变长对象(list、tuple等)
  3. 类型对象通过槽位定义对象行为
  4. **type**既是类型又是元类,是自身的实例
  5. **is比较身份(id),==**比较值(__eq__

📝 发现内容有误?点击此处直接编辑

← 上一篇 Python字节码执行引擎
下一篇 → Python导入系统实现
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库