Python源码剖析

Python源码剖析

深度探索动态语言核心技术

8.8806 评价豆瓣读书
免费试读

作品简介

作为主流的动态语言,Python不仅简单易学、移植性好,而且拥有强大丰富的库的支持。此外,Python强大的可扩展性,让开发人员既可以非常容易地利用C/C++编写Python的扩展模块,还能将Python嵌入到C/C++程序中,为自己的系统添加动态扩展和动态编程的能力。

为了更好地利用Python语言,无论是使用Python语言本身,还是将Python与C/C++交互使用,深刻理解Python的运行原理都是非常重要的。本书以CPython为研究对象,在C代码一级,深入细致地剖析了Python的实现。书中不仅包括了对大量Python内置对象的剖析,更将大量的篇幅用于对Python虚拟机及Python高级特性的剖析。通过此书,读者能够透彻地理解Python中的一般表达式、控制结构、异常机制、类机制、多线程机制、模块的动态加载机制、内存管理机制等核心技术的运行原理,同时,本书所揭示的动态语言的核心技术对于理解其他动态语言,如 Javascript、Ruby等也有较大的参考价值。

本书适合于Python程序员、动态语言爱好者、C程序员阅读。

陈儒,计算机科学与工程专业硕士,问天(北京)信息技术有限公司技术负责人,致力于信息检索方向的研究与开发。

作品目录

  1. 第0章 Python源码剖析——编译Python
  2. 0.1 Python总体架构
  3. 0.2 Python源代码的组织
  4. 0.3 Windows环境下编译Python
  5. 0.4 Unix/Linux环境下编译Python
  6. 0.5 修改Python源代码
  7. 0.6 通往Python之路
  8. 0.7 一些注意事项
  9. 第1部分 Python内建对象
  10. 第1章 Python对象初探
  11. 1.1 Python内的对象
  12. 1.2 类型对象
  13. 1.3 Python对象的多态性
  14. 1.4 引用计数
  15. 1.5 Python对象的分类
  16. 第2章 Python中的整数对象
  17. 2.1 初识PyIntObject对象
  18. 2.2 PyIntObject对象的创建和维护
  19. 2.3 Hack PyIntObject
  20. 第3章 Python中的字符串对象
  21. 3.1 PyStringObject与PyString_Type
  22. 3.2 创建PyStringObject对象
  23. 3.3 字符串对象的intern机制
  24. 3.4 字符缓冲池
  25. 3.5 PyStringObject效率相关问题
  26. 3.6 Hack PyStringObject
  27. 第4章 Python中的List对象
  28. 4.1 PyListObject对象
  29. 4.2 PyListObject对象的创建与维护
  30. 4.3 PyListObject对象缓冲池
  31. 4.4 Hack PyListObject
  32. 第5章 Python中的Dict对象
  33. 5.1 散列表概述
  34. 5.2 PyDictObject
  35. 5.3 PyDictObject的创建和维护
  36. 5.4 PyDictObject对象缓冲池
  37. 5.5 Hack PyDictObject
  38. 第6章 最简单的Python模拟——Small Python
  39. 6.1 Small Python
  40. 6.2 对象机制
  41. 6.3 解释过程
  42. 6.4 交互式环境
  43. 第2部分 Python虚拟机
  44. 第7章 Python的编译结果——Code对象与pyc文件
  45. 7.1 Python程序的执行过程
  46. 7.2 Python编译器的编译结果——PyCodeObject对象
  47. 7.3 Pyc文件的生成
  48. 7.4 Python的字节码
  49. 7.5 解析pyc文件
  50. 第8章 Python虚拟机框架
  51. 8.1 Python虚拟机中的执行环境
  52. 8.2 名字、作用域和名字空间
  53. 8.3 Python虚拟机的运行框架
  54. 8.4 Python运行时环境初探
  55. 第9章 Python虚拟机中的一般表达式
  56. 9.1 简单内建对象的创建
  57. 9.2 复杂内建对象的创建
  58. 9.3 其他一般表达式
  59. 第10章 Python虚拟机中的控制流
  60. 10.1 Python虚拟机中的if控制流
  61. 10.2 Python虚拟机中的for循环控制流
  62. 10.3 Python虚拟机中的while循环控制结构
  63. 10.4 Python虚拟机中的异常控制流
  64. 第11章 Python虚拟机中的函数机制
  65. 11.1 PyFunctionObject对象
  66. 11.2 无参函数调用
  67. 11.3 函数执行时的名字空间
  68. 11.4 函数参数的实现
  69. 11.5 函数中局部变量的访问
  70. 11.6 嵌套函数、闭包与decorator
  71. 第12章 Python虚拟机中的类机制
  72. 12.1 Python中的对象模型
  73. 12.2 从type对象到class对象
  74. 12.3 用户自定义class
  75. 12.4 从class对象到instance对象
  76. 12.5 访问instance对象中的属性
  77. 12.6 千变万化的descriptor
  78. 第13章 Python运行环境初始化
  79. 13.1 线程环境初始化
  80. 13.2 系统module初始化
  81. 13.3 激活Python虚拟机
  82. 第14章 Python模块的动态加载机制
  83. 14.1 import前奏曲
  84. 14.2 Python中import机制的黑盒探测
  85. 14.3 import机制的实现
  86. 14.4 Python中的import操作
  87. 14.5 与module有关的名字空间问题
  88. 第15章 Python多线程机制
  89. 15.1 GIL与线程调度
  90. 15.2 初见Python Thread
  91. 15.3 Python线程的创建
  92. 15.4 Python线程的调度
  93. 15.5 Python子线程的销毁
  94. 15.6 Python线程的用户级互斥与同步
  95. 15.7 高级线程库——threading
  96. 第16章 Python的内存管理机制
  97. 16.1 内存管理架构
  98. 16.2 小块空间的内存池
  99. 16.3 循环引用的垃圾收集
  100. 16.4 Python中的垃圾收集
载入中

热门划线

  1. 在Python中,对象机制的核心其实非常简单,一个是引用计数,一个就是类型信息。52 人
  2. 在Python中,对象就是为C中的结构体在堆上申请的一块内存,一般来说,对象是不能被静态初始化的,并且也不能在栈空间上生存。唯一的例外就是类型对象,Python中所有的内建的类型对象(如整数类型对象,字符串类型对象)都是被静态初始化的。38 人
  3. 在Python中,一个对象一旦被创建,它在内存中的大小就是不变的了。这就意味着那些需要容纳可变长度数据的对象只能在对象内维护一个指向一块可变大小的内存区域的指针。31 人
  4. 当进入一个新的名字空间,或者说作用域时,我们就算是进入了一个新的Code Block了。25 人
  5. 这意味着Python的import机制会触发pyc文件的生成。22 人
  6. 在程序运行期间,编译结果存在于内存的PyCodeObject对象中;而Python结束运行后,编译结果又被保存到了pyc文件中。当下一次运行相同的程序时,Python会根据pyc文件中记录的编译结果直接建立内存中的PyCodeObject对象,而不用再次对源文件进行编译了。21 人
  7. 对象是数据以及基于这些数据的操作的集合19 人
  8. 整数对象池18 人
  9. Python编译器在对Python源代码进行编译的时候,对于代码中的一个Code Block,会创建一个PyCodeObject对象与这段代码对应。那么如何确定多少代码算是一个Code Block呢?事实上,Python有一个简单而清晰的规则:当进入一个新的名字空间,或者说作用域时,我们就算是进入了一个新的Code Block了。18 人
  10. 由一个赋值语句引进的名字在这个赋值语句所在的作用域里是可见(起作用)的16 人
  11. 官方推荐的做法是通过利用PyStringObject对象的join操作来对存储在list或tuple中的一组PyStringObject对象进行连接操作,这种做法只需要分配一次内存,执行效率将大大提高。15 人
  12. 一个PyTypeObject对象就是Python中对面向对象理论中“类”这个概念的实现14 人
  13. 需要注意的是,在Python的各种对象中,类型对象是超越引用计数规则的。类型对象“跳出三界外,不再五行中”,永远不会被析构。每一个对象中指向类型对象的指针不被视为对类型对象的引用。14 人
  14. 当产生散列冲突时,Python会通过一个二次探测函数f,计算下一个候选位置addr,如果位置addr可用,则可将待插入元素放到位置addr;如果位置addr不可用,则Python会再次使用探测函数f,获得下一个候选位置,如此不断探测,总会找到一个可用的位置。13 人
  15. malloc12 人
  16. 在这片内存中,存储着一系列的数据以及可以对这些数据进行修改或读取操作的一系列代码。12 人
  17. http://code.google.com/p/python-cobra/11 人
  18. Python中通过“+”进行字符串连接的方法效率极其低下,其根源在于Python中的PyStringObject对象是一个不可变对象。这就意味着当进行字符串连接时,实际上是必须要创建一个新的PyStringObject对象。这样,如果要连接N个PyStringObject对象,那么就必须进行N-1次的内存申请及内存搬运的工作。毫无疑问,这将严重影响Python的执行效率。11 人
  19. 研究表明,当散列表的装载率大于2/3时,散列冲突发生的概率就会大大增加。11 人
  20. Python程序的执行原理和Java程序、C#程序的执行原理都可以用两个词囊括——虚拟机、字节码。11 人
  21. 我们可以总结出Python中赋值语句行为的共同之处:□ 创建一个对象obj□ 将obj“赋给”一个名字name11 人
  22. 为什么在函数的实现中没有使用local名字空间呢?这是因为函数中的局部变量总是固定不变的,所以在编译时就能确定局部变量使用的内存空间的位置,也能确定访问局部变量的字节码指令应该如何访问内存。有了这些信息,Python就能使用静态的方法来实现局部变量,而不需要借助于动态地查找PyDictObject对象的技术,毕竟,函数调用实在是太普遍了,静态的方法可以极大地提高函数执行的效率。11 人
  23. 在Python中,任何一个对象都有一个type,可以通过对象的__class__属性获得。任何一个instance对象的type都是一个class对象,而任何一个class对象的type都是metaclass对象。在大多数情况下这个metaclass都是<type ‘type’>,而在Python内部,它实际上对应的就是PyType_Type。11 人
  24. Python中所有的内建的类型对象(如整数类型对象,字符串类型对象)都是被静态初始化的。10 人
  25. PyObject_HEAD10 人
  26. 在PyObject的定义中,整型变量ob_refcnt与Python的内存管理机制有关,它实现了基于引用计数的垃圾收集机制。对于某一个对象A,当有一个新的PyObject *引用该对象时,A的引用计数应该增加;而当这个PyObject *被删除时,A的引用计数应该减少。当A的引用计数减少到0时,A就可以从堆上被删除,以释放出内存供别的对象使用。10 人
  27. 在PyObject中定义的内容仅仅是每一个Python对象都必须拥有的一部分内容10 人
  28. PyType_Type在Python的类型机制中是一个至关重要的对象,所有用户自定义class所对应的PyTypeObject对象都是通过这个对象创建的。10 人
  29. 在编译过程中,这些包含在Python源代码中的静态信息都会被Python编译器收集起来,编译的结果中包含了字符串,常量值,字节码等在源代码中出现的一切有用的静态信息。在Python运行期间,这些源文件中提供的静态信息最终会被存储在一个运行时的对象中,当Python运行结束后,这个运行时对象中所包含的信息甚至还会被存储在一种文件中。这个对象和文件就是我们这章探索的重点:PyCodeObject对象和pyc文件。10 人
  30. Lib :该目录包含了Python自带的所有标准库,Lib中的库都是用Python语言编写的。9 人
  31. Modules中的模块是那些对速度要求非常严格的模块,而有一些对速度没有太严格要求的模块,比如os,就是用Python编写,并且放在Lib目录下的。9 人
  32. 第一种是通过Python C API来创建,第二种是通过类型对象PyInt_Type。9 人
  33. PyObject中的ob_refcnt是一个32位的整形变量,这实际蕴含着Python所做的一个假设,即对一个对象的引用不会超过一个整形变量的最大值。9 人
  34. 每一个对象中指向类型对象的指针不被视为对类型对象的引用。9 人
  35. 在每一个对象创建的时候,Python提供了一个_Py_NewReference(op)宏来将对象的引用计数初始化为1。9 人
  36. 在Python的实现中,对某些会频繁执行的代码,都会同时提供函数和宏两种版本9 人
  37. 实际上,不同PyIntBlock对象的objects中的空闲内存块是被链接在一起的,形成了一个单向链表,指向表头的指针正是free_list。9 人
  38. 由于内存共享,Python用于实现该对象池的内存与历史上创建的整数对象的个数无关,而仅仅与同一时刻共存的整数对象个数的最大值有关9 人
  39. 在Python源码中的注释显示,预存字符串的hash值和这里的intern机制将Python虚拟机的执行效率提升了20%。9 人
  40. 名字空间可以一个套一个地形成一条名字空间链,Python虚拟机在执行的过程中,会有很大一部分时间消耗在从这条名字空间链中确定一个符号所对应的对象是什么。9 人
  41. 这个域是Python向pyc文件中写入字符串或从其中读出字符串的关键所在,当向pyc中写入时,strings会指向一个PyDictObject对象;而从pyc中读出时,strings则会指向一个PyListObject对象。9 人
  42. 一个对象的名字空间中的所有名字都称为对象的属性9 人
  43. 由一个赋值语句引进的名字在这个赋值语句所在的作用域里是可见(起作用)的,而且在其内部嵌套的每个作用域里也可见,除非它被嵌套于内部的,引进同样名字的另一条赋值语句所遮蔽。9 人
  44. 运行时环境是一个全局的概念,而执行环境实际就是一个栈帧,是一个与某个Code Block对应的概念。9 人

喜欢「Python源码剖析」的人也喜欢