17-Python类机制深度解析-回顾Python中的对象模型
17-Python类机制深度解析-回顾Python中的对象模型楔子这一次我们就来看看Python中类是怎么实现的,我们知道C不是一个面向对 象语言,而Python却是一个面向对象的语言,那么在Python的底层,是如何使用C来支持Python实现面向对象的功能呢?带着这些疑问,我们下面开始剖析python中类的实现机制。另外,在Python2中存在着经典类(classic class)和新式类(new style class),但是到Python3中,经典类已经消失了。并且python2官方都不维护了,因此我们这一章只会介绍新式类。
另外关于类,我们在最开始介绍对象关系模型的时候其实说了不少,这里会再简单温习一遍。
Python中的对象模型我们在最开始介绍对象的时候就说了,在面向对象的理论中,有两个核心的概念:类和实例。类可以看成是一个模板,那么实例就是根据这个模板创建出来的对象。可以想象成docker的镜像和容器。但是在Python中,一切都是对象,所以类和实例都是对象,类叫做类对象,实例叫做实例对象。如果想用大白话来描述清楚的话,这无疑是一场灾难,我们还是需要使用一些专业术语来描 ...
Flexible and Optimal Dependency Management via Max-SMT
d9eba399523fe401e434f6396d459a7a735596707e1aa1664e34b3a934e193fb66dbe0c4d51c9fa69a2536673e082387beb384fc7e9571a45b05dab4bae28e3ad02fa6f5716c76f86441d9d3e9212ed02f37f468158990dbd3000d277ebb3c54fa6fd04ea66b7013e588a75bff24eabd4d58fd399d719b92f34af838af0594936b1307ae443c5be9f4441cb6a316759f5363fe2c4065308fecac3c894e8afc373c4848938963bde828dfb265f2c4e86920acf7fef5b8260bfe96c683a382888a4b7b2b4f5127bb8302b4e8b37d30bcae841f09babec778ef1be3c878fc88c4bc0ac3be8f66012bb885ac55d65cafe25bd5656bcb283b5dfe7 ...
16-闭包的底层实现
16-闭包的底层实现以及调用楔子上一篇我们看了函数是如何调用的,这一次我们看一下函数中局部变量的访问、以及闭包相关的知识。
函数中局部变量的访问我们说过函数的参数和函数内部定义的变量都属于局部变量,所以它也一样是通过静态的方式进行访问。
123456789101112131415161718192021222324252627x = 123def foo(): global x a = 1 b = 2# a和b是局部变量,x是全局变量,因此是2print(foo.__code__.co_nlocals) # 2def bar(a, b): passprint(bar.__code__.co_nlocals) # 2def bar2(a, b): a = 1 b = 2 c = 3print(bar2.__code__.co_nlocals) # 3
因此我们看到,无论是参数还是内部新创建的变量,本质上都是局部变量。并且我们发现如果函数内部定义的变量如果和函数参数一致,那么参数就没用了,很好理解,因为本质上就相当于重新赋值罢了,此时外面无 ...
15-函数在底层是如何被调用的
15-函数在底层是如何被调用的楔子在上一篇博客中,我们说了Python函数的底层实现,并且还演示了如何自定义一个函数,虽然这在工作中没有太大意义,但是可以让我们深刻理解函数的行为。此外我们还介绍了如何获取函数的参数,而这一次我们就来看看函数如何调用的。
函数的调用1234567891011s = """def foo(): a, b = 1, 2 return a + bfoo()"""if __name__ == '__main__': import dis dis.dis(compile(s, "call_function", "exec"))
我们以一个非常简单的函数为例,看看它的字节码:
123456789101112131415161718192021 2 0 LOAD_CONST 0 (<code object foo at 0x00000219BA3F1450, file ...
14-函数在底层的数据结构以及创建方式
14-函数在底层的数据结构、以及它的创建方式楔子函数是任何一门编程语言都具备的基本元素,它可以将多个动作组合起来,一个函数代表了一系列的动作。当然我们之前说函数也是一个变量,该变量指向一个函数。而且在调用函数时会干什么来着,没错,要在运行时栈中创建栈帧,用于函数的执行。
那么下面就来看看函数在C中是如何实现的,生得一副什么模样。
PyFunctionObject对象我们说过Python中一切皆对象,函数也不例外。在Python中,函数这种抽象机制是通过PyFunctionObject对象实现的,位于 *Include/funcobject.h* 中。
12345678910111213141516171819202122typedef struct { PyObject_HEAD /* 头部信息, 不用多说 */ PyObject *func_code; /* 函数的PyCodeObject对象, 因为函数就是根据该PyCodeObject对象创建的 */ PyObject *func_globals; ...
13-剖析Python的流程控制语句
13-剖析Python的流程控制语句(if、for、while),以及异常捕获机制楔子在上一章中,我们介绍了Python虚拟机中常见的字节码指令。但我们的流程都是从上往下顺序执行的,在执行的过程中没有任何变化,但是显然这是不够的,因为怎么能没有流程控制呢。下面我们来看看Python所提供的流程控制手段,其中也包括异常检测机制。
Python虚拟机中的if控制流if字节码if语句算是最简单也是最常用的控制流语句,那么它的字节码是怎么样的呢?当然我们这里的if语句指的是if、elif、elif…、else整体,里面的if、某个elif或者else叫做该if语句的分支。
123456789101112131415s = """gender = "男"if gender == "男": print("nice muscle")elif gender == "女": print("白い肌")else: print("秀吉")&qu ...
12-剖析字节码指令
12-剖析字节码指令,从不一样的角度观测Python源代码的执行过程上一章中,我们通过_PyEval_EvalFrameDefault看到了Python虚拟机的整体框架,那么这一章我们将深入到_PyEval_EvalFrameDefault的各个细节当中,深入剖析Python的虚拟机,在本章中我们将剖析Python虚拟机是如何完成对一般表达式的执行的。这里的一般表达式包括最基本的对象创建语句、打印语句等等。至于if、while等表达式,我们将其归类于控制流语句,对于Python中控制流的剖析,我们将留到下一章。
简单回顾这里我们通过问与答的方式,简单回顾一下前面的内容。
请问 Python 程序是怎么运行的?是编译成机器码后在执行的吗?
不少初学者对 *Python* 存在误解,以为它是类似 *Shell* 的解释性脚本语言,其实并不是。虽然执行 *Python* 程序的 称为 *Python* 解释器,但它其实包含一个 “编译器” 和一个 “虚拟机”。
当我们在命令行敲下 python xxxx.py 时,*python* 解释器中的编译器首先登场,将 *P ...
11-探索Python虚拟机和字节码的奥秘
11-探索Python虚拟机执行字节码的奥秘这一次我们就来剖析Python运行字节码的原理,我们知道Python虚拟机是Python的核心,在源代码被编译成PyCodeObject对象时,就将由Python虚拟机接手整个工作。Python虚拟机会从PyCodeObject中读取字节码,并在当前的上下文中执行,直到所有的字节码都被执行完毕。
Python虚拟机的执行环境Python的虚拟机实际上是在模拟操作系统运行可执行文件的过程,我们先来看看在一台普通的x86的机器上,可执行文件是以什么方式运行的。在这里主要关注运行时栈的栈帧,如图所示:
x86体系处理器通过栈维护调用关系,每次函数调用时就在栈上分配一个帧用于保存调用上下文以及临时存储。CPU中有两个关键寄存器,rsp指向当前栈顶,rbp指向当前栈帧。每次调用函数时,调用者(Caller)负责准备参数、保存返回地址,并跳转到被调用函数中执行代码;作为被调用者(Callee),函数先将当前rbp寄存器压入栈(保存调用者栈帧位置),并将rbp设为当前栈顶(保存当前新栈帧的位置)。由此,rbp寄存器与每个栈帧中保存调用者栈帧地址一起完美地 ...
10-PyCodeObject对象和pyc文件
10-Python中的PyCodeObject对象与pyc文件楔子当我们想要执行一个py文件的时候,只需要python xxx.py即可,但是你有没有想过这背后的流程是怎么样的呢?从这里开始我们就开始进入到Python虚拟机的环节了,之前都是在介绍Python中的一些内置对象,不过虚拟机的执行流程、以及背后的原理却更是值得我们关注的。
这里我们先来说一下Python执行py文件的流程:
1. 首先将文件里面的内容读取出来, 所以从这个角度上讲, 文件名不一定非要是.py结尾, .txt也是可以的, 只要文件里面的内容符合Python代码规范即可
2. 读取文件里面的内容之后会对其进行分词, 将源代码切分成一个一个的token
3. 然后Python编译器会对token进行语法解析, 建立抽象语法树(AST, abstract syntax tree)
4. 编译器再将得到AST编译成字节码
5. 最终由Python虚拟机来执行字节码
首先我们从中看到了Python编译器、Python虚拟机,而且我们平常还会说Python解释器,那么三者之间有什么区别呢?
实际上Python解释 ...
09-字典和集合的底层实现
09-解密Python中字典和集合的底层实现,深度分析哈希表楔子Python的字典是一种映射型容器对象,保存了键(key)到值(value)的映射关系。通过字典,我们可以快速的实现值的查找,json这种数据结构也是借鉴了Python中的字典。而且字典在Python中是经过高度优化的,因为Python底层也在大量的使用字典这种数据结构。
那么这次我们就来全面分析一下Python中的字典。
基本使用我们先来回顾一下字典的基本使用,然后再来分析它的一些特性以及底层实现。
创建一个字典:
1234567891011121314151617181920212223242526272829303132# 创建一个字典d = {"a": 1, "b": 2}print(d) # {'a': 1, 'b': 2}# 或者我们还可以通过dict, 传入关键字参数即可d = dict(a=1, b=2, c=3, d=4)print(d) # {'a': ...