标题
7 Python 对象模型
8 PyObject 和 PyVarObject
9 引用计数
10 垃圾收集器
11 内存分配器
12 对象布局和类型槽
13 内置对象实现
14 字符串、字节和 Unicode
15 列表、元组和数组
16 词典和词典集
17 整数、浮点数和复数
  • 7.Python对象模型

    7.Python 对象模型 Python 对象模型是 CPython 的基础。 Python 中运行的所有内容最终都会成为对对象的操作:整数、字符串、列表、模块、函数、类、异常、框架,甚至编译后的代码。 在语言层面,Python 表示每个对象都有一个标识、一个类型和一个值。对象标识在创建后保持固定, is 比较身份,并且 id() 返回表示该身份的整数。 ([Python 文档][1]) CPython 使用 C 结构、对象头、引用计数、类型对象和操作槽来实现此模型。 7.1 对象、值和身份 Python 对象具有三个核心属性。 物业 意义 示例 身份 对象的稳定身份 id(x) 类型 对象的运行时类型 type(x) 价值 对象所表示的数据 42 , "abc" , [1, 2] 例子:```python x = [1, 2, 3] y = x print(x is y) # True print(type(x)) # <class 'list'> print(x) # [1, 2, 3] ` x ` 和 ` y…

  • 8.PyObject 和 PyVarObject

    #8. PyObject 和 PyVarObject PyObject 和 PyVarObject 是 CPython 对象背后的基本布局。它们不是 Python 类。它们是 C 级结构约定,允许运行时通过通用指针类型处理许多不同的对象实现。 在运行时,CPython 中的大多数对象引用表示为:```c PyObject * ## 8.1 公共对象头 一个简化的 ` PyObject ` 看起来像这样: ``` c typedef struct { Py_ssize_t ob_refcnt ; PyTypeObject * ob_type ; } PyObject ; ``` 真正的定义使用宏和依赖于构建的字段,特别是在调试构建、跟踪构建和现代 CPython 版本中。但本质思想是稳定的: ``` text PyObject reference count type pointer ``` 引用计数跟踪所有权。 类型指针告诉 CPython 对象的行为方式。 每个普通的 CPython 对象都以这个公共标头开始。因此,运行时可以接收 ` PyObject *` 并在编译时不知道完整的具体结构的情况下检查其类型。 ## 8.2 为什么每个对象都以相同的方式启动 考虑下面的 Python 代码:…

  • 9. 引用计数

    9. 引用计数 引用计数是 CPython 的主要内存管理机制。每个普通对象都带有当前指向它的强引用计数。当该计数降至零时,CPython 可以立即销毁该对象。 这种设计是 CPython 与许多其他语言运行时之间最明显的区别之一。 CPython 确实有一个循环垃圾收集器,但该收集器补充了引用计数。大多数对象是通过引用计数转换来回收的,而不是通过定期跟踪来回收。 9.1 核心思想 当某个对象拥有对它的引用时,Python 对象就会保持活动状态。 从概念上讲:```text object created reference count = 1 another owner stores the object reference count += 1 an owner releases the object reference count -= 1 reference count reaches 0 object is deallocated 例子: python x = [] y = x del x del y ```列表对象被创建并绑定到 x 。装订 y = x 创建对同一列表的另一个引用。正在删除 x 删除一个引用。正在删除 y 删除剩余的引用,因此可以销毁列表。…

  • 10. 垃圾收集器

    10. 垃圾收集器 CPython 使用引用计数作为其主要内存管理机制。一旦最后一个强引用消失,引用计数就会销毁大多数对象。 引用计数有一个主要限制:它无法自行回收引用循环。 垃圾收集器的存在是为了找到容器对象的不可达循环并回收它们。它是引用计数的补充,而不是替代。 10.1 为什么引用计数需要帮助 仅当没有强引用指向对象时,引用计数才会达到零。 这适用于普通对象图:```python x = [] del x 它不适用于循环: ``` python a = [] b = [] a . append ( b ) b . append ( a ) del a del b ``` 删除两个名称后,列表仍然相互引用: ``` text list A ---> list B list B ---> list A ``` 它们的引用计数保持非零。但实时 Python 代码无法访问它们。 引用计数看到本地所有权。垃圾收集看到了可达性。 ## 10.2 垃圾收集器跟踪什么 CPython 不需要跟踪循环垃圾收集器中的每个对象。 不能包含对其他 Python 对象的引用的对象不能自行形成循环。示例包括许多整数、浮点数和简单字符串。 收集器主要跟踪类似容器的对象: ``` text…

  • 11. 内存分配器

    11. 内存分配器 CPython 不断分配内存。每个整数对象、列表对象、框架、元组、字典条目数组、字符串缓冲区、代码对象、异常、模块和函数都需要内存。分配器系统的存在是为了使这些分配快速、结构化、可调试且跨平台可移植。 CPython 不只使用一个分配器。它使用多个分配器域和层。小的 Python 对象通常会通过 CPython 的专用小对象分配器,而较大的缓冲区可能会通过平台分配器。 11.1 为什么 CPython 有自己的分配器 Python 程序创建许多短暂的对象。 python for i in range(1_000_000): x = (i, i + 1) 该循环分配许多元组对象和整数引用。如果每个小对象分配都直接进入系统 malloc ,开销会很大。 CPython 的分配器系统通过以下方式改进了这一点:```text serving small object allocations quickly grouping small allocations into arenas and pools reducing calls into the platform allocator supporting debug hooks separating allocator domains making object allocation behavior predictable enough for internals work ## 11.2 分配器域 CPython 将内存分配分为多个域。…

  • 12. 对象布局和类型槽

    12. 对象布局和类型槽 CPython 将每个运行时值表示为一个对象。每个对象都有一个内存布局,每个对象的类型描述了如何解释该内存。 对象布局答案: text What fields exist inside this object? Where are the references to other Python objects? How large is one instance? Does the object have variable-sized trailing storage? Does the object participate in cyclic garbage collection? 类型槽答案:```text How is this object called? How is it deallocated? How does attribute lookup work? How does indexing work? How does addition work? How does iteration work? How is it…

  • 13. 内置对象实现

    13. 内置对象实现 内置对象是 Python 核心类型背后的具体数据结构。它们是普通的 Python 对象,因为它们具有标识、类型、引用计数、支持的属性以及由类型槽定义的行为。它们很特别,因为它们的存储和操作是直接用 C 实现的。 本章给出了一个大致的地图。后面的章节将深入探讨字符串、列表、元组、字典、集合、数字、函数、模块和框架。 13.1 内置函数是类型对象 内置类型,例如 list , dict , 或者 int 本身就是一个Python对象。 python print(type(list)) # <class 'type'> print(type(dict)) # <class 'type'> print(type(int)) # <class 'type'> 实例指向其类型对象。 python xs = [1, 2, 3] print(type(xs)) # <class 'list'> C级:```text xs ---> PyListObject ob_refcnt ob_type ----> PyList_Type ob_size ob_item allocated ## 13.2 为什么用 C 实现内置函数 内置类型位于 Python 执行最热门的路径上。 常见的操作包括: ``` text integer arithmetic string hashing…

  • 14. 字符串、字节和 Unicode

    14. 字符串、字节和 Unicode 文本和二进制数据是 Python 中独立的对象族。 str 代表 Unicode 文本。 bytes 表示不可变的二进制数据。 bytearray 表示可变的二进制数据。 这种分离是 Python 3 最重要的运行时设计选择之一。文本具有字符和编码。二进制数据有字节。 CPython 使用不同的对象布局、API 和不变量来实现这些概念。 14.1 文本与二进制数据 字符串是文本: python id="ly45du" s = "hello" bytes 对象是二进制数据: python id="1wh8hi" b = b"hello" 它们对于 ASCII 内容可能看起来相似,但它们是不同的类型。 python id="iqtxra" print(type("hello")) # <class 'str'> print(type(b"hello")) # <class 'bytes'> Python 不会隐式混合它们: python id="8bzmko" "hello" + b"world" # TypeError 这是故意的。组合文本和字节需要编码决策。```python id="8w5t7o" text = "hello" data = text.encode("utf-8") again = data.decode("utf-8") ##…

  • 15. 列表、元组和数组

    15.列表、元组和数组 列表、元组和类似数组的对象表示有序集合。它们都支持索引访问,但具有不同的存储模型、可变性规则和性能权衡。 列表是对象引用的可变序列。 元组是对象引用的不可变序列。 类似数组的对象存储紧凑类型的数据或公开连续的缓冲区。 这些区别很重要,因为 CPython 容器存储引用,除非该类型是专门为原始存储设计的。 15.1 有序集合 Python 有多种有序集合类型。 |类型 | 可变 |商店 |主要用途| | ------------- | -------------:| ----------------- | ------------------------------------------- | | list | 是的 |对象参考|一般可变序列 | | tuple | 没有 |对象参考|固定记录、不可变组 | | array.array | 是的 |原始类型值 |紧凑的数字存储 | | bytes | 没有 |原始字节 |不可变的二进制数据 | | bytearray | 是的 |原始字节 |可变二进制数据 | | memoryview |视图相关 |原始缓冲区视图 |零拷贝缓冲区访问 | 列表和元组可以存储任何类型的对象: python xs = [1, "two",…

  • 16. 字典和集合

    16. 字典和集合 字典和集合是 CPython 的主要哈希表容器。字典将键映射到值。集合存储没有关联值的键。 它们在 Python 中无处不在:```text id="cp7dx7" module globals class namespaces instance attributes keyword arguments function annotations import caches memoization tables membership indexes deduplication sets ## 16.1 字典语义 字典将可散列键映射到值 。``` python id = "cvrlq9" d = { "name" : "Ada" , "age" : 36 , } print ( d [ "name" ]) # Ada ``` 键必须是可散列的 。 值可以是任何对象 。``` python id = "mb4tqx" d = {} d […

  • 17. 整数、浮点数和复数

    17. 整数、浮点数和复数 Python 的数字对象是具有专门实现的普通对象。它们参与与列表、字典、函数、类和模块相同的对象模型:每个值都有一个对象头、一个类型指针、引用计数行为和用于操作的类型槽。 主要的内置数字类型有: |类型 | Python 名称 |主要代表| | -------------- | ----------- | ------------------------ | | |整数| int |任意精度整数 | |布尔 | bool |单例子类 int | |浮点数| float | C双| |复杂| complex |一对C双打| 这些类型在 Python 级别看起来很简单,但每种类型都具有重要的运行时权衡。 17.1 数字对象就是对象 Python 整数通常不会作为原始 CPU 整数存储在 Python 变量中。 python x = 42 在 CPython 级别, x 指的是Python整型对象。 从概念上讲: text x ---> PyLongObject object header integer payload 对于浮点数和复数也是如此。 python a = 1.5 b…