置顶
type
status
slug
summary
tags
category
icon
password
URL
date
python
python解释器 = 编译器 + 虚拟机
编译过程: 源码->解析数->AST(抽象语法书)->符号表->字节码对象
python编译器会从程序运行目录、安装设置路径等地方搜索python文件,将其编译成
.pyc
文件存储起来。如果源码没有变化,下次直接使用。.pyc
文件存储PyCodeObject对象,该对象包含了局部变量表、符号表、字节码等属性。python的对象和数据结构保存在一个Heap中,清理无用对象是通过引用计数法。
调用时会有线程获取对象字节码,拿到GIL锁(全局解释器锁)的线程在栈中执行,执行过程中会动态判断类型。即使在 python 进程中存在多个线程,在任何给定时间,只有一个线程可以主动执行 CPU 密集的任务。 这是因为执行线程必须持有全局解释器锁(GIL)才能在 python 虚拟机中执行字节代码。
GIL 是大多数情况下为什么在 python 中增加线程数无法加速 CPU 密集型计算的主要原因。 实际上,与单线程程序相比,添加线程会对程序的性能产生不利影响,因为增加了线程切换和等待相关的成本。
python的线程调度并不是又时间片为标准,而是以执行字节码数量为标准。执行够一定数量后会释放GIL。
builtins
字段是对内置 sys
模块的引用,该模块的内容是 len
,enumerate
等内置函数的集合- 类变量、成员变量
类体内、函数体外定义的变量。 可以通过类名调用。只
- 作用域
Local、Enclosing、Global、builtin
python的属性保存在__dict__中,foo.bar等价于
foo.__dict__['bar']
- 类变量继承取值
- 类变量
- 实例变量
如果该变量在该类中有定义,则使用该值。
如果没有,将搜索父类,多继承时采用C3方法,一般不存在交叉的类都是从左到右顺序搜索。搜索过程中如果前面父类的值被重新赋值,则类变量值将改变成该值
与类变量类似,但是只会继承最初的值,父类对象的值改变不会影响子类的属性
- MRO Method Resolution Order,即方法解析顺序
- 经典类 从左至右的深度优先遍历,会重复
- py 2.2新式类 从左至右的深度优先遍历,但是如果遍历中出现重复的类,只保留最后一个
- 新式类 C3算法,python3使用这个
L[object] = [object]
L[C(B1…BN)] = [C] + merge(L[B1]…L[BN], [B1]…[BN])
- 检查第一个列表的头元素(如
L[B1]
的头),记作H
。 - 若
H
未出现在其它列表的尾部,则将其输出,并将其从所有列表中删除,然后回到步骤1;否则,取出下一个列表的头部记作H
,继续该步骤。 - 重复上述步骤,直至列表为空或者不能再找出可以输出的元素。如果是前一种情况,则算法结束;如果是后一种情况,说明无法构建继承关系,Python 会抛出异常
定义类继承链中如何对类属性和方法进行查找,保证属性查找不会出现冲突。
有三类mro
把类
C
的线性化(MRO)记为 L[C] = [C1, C2,…,CN]
。其中 C1
称为 L[C]
的头,其余元素 [C2,…,CN]
称为尾。如果一个类 C
继承自基类 B1
、B2
、……、BN
,那么我们可以根据以下两步计算出 L[C]
:这里的关键在于
merge
,其输入是一组列表,按照如下方式输出一个列表:- namedtuple
返回的是一个名为
typename
的元组子类。这个返回的子类用于创建类似元组的对象,这些对象具有可通过属性查找访问的字段以及可索引和可迭代的字段。- 类变量的并发问题,怎么解决。
- 钻石继承
eg:多继承的两个父类继承自同一个超类。子类多次调用会导致超类重复实例化,方法重复执行
解决方式:super(子类名,selef).__intit__(),底层通过__mro__实现,将继承的图结构转换成列表。
- python中的容器 list、dict等本身就是线程安全的,并不是通过互斥锁实现,通过GIL实现