python高级--知识点提高
GIL(全局解释锁)
简介
顾名思义这是一个锁,它的作用保证了同一个时刻只能一个线程可以运行代码,也就是说不管你是几线程的cpu但在这一刻只能一个线程运行,其他线程没法运行,只有当遇到堵塞时才会切换进程。GIL与python语言没有任何关系,这是python解释器的问题,cpython解释器有这个问题,jpython解决了这个问题。只对线程有效。
GIL面试题
描述python GIL的概念,以及它对python多线程的影响,如果编写一个爬虫程序,并阐述多线程程序是否比单线程性能提升,并解释原因。
答
1、Python语言与GIL没有任何关系,只是由于历史原因在Cpython解释器。难以移除GIL
2、GIL全局解释器锁每个线程在执行的过程中都需要先获取GIL,保证同一时刻只能有一个线程执行代码
3、线程释放GIL锁的情况当线程遇到堵塞(IO)操作之前,在执行完毕后会重新获取GIL锁
4、多线程程序是比单线程性能高的,因为单线程只能在当这个任务完成后才可以执行下一个,多线程在执行时会遇到堵塞所以在堵塞的时候可以执行另一个线程。
解决方法
1、使用Jpython解释器
2、使用其他语言
深拷贝、浅拷贝
简单的深拷贝、浅拷贝
浅拷贝
例如Python中
a = 5;
b = a;
此时的拷贝是一个引用,就是首先定义一个变量a它指向一个int类型的数据,
然后将变量a赋给变量b,此时是b也指向a指向的那一个地址。深拷贝
例如在c语言中
int a = 5;
定义一个变量是在为该变量在内存中开辟一块int的空间,
int b = a;
赋值时;
是将该空间复制了一份赋给b存储在另一块空间中,相互之间没有关联## 复杂的深拷贝、浅拷贝
python中的copy模块
copy.copy(变量)方法
copy.deepcopy(变量)方法
拷贝变量
在拷贝变量时两个都是简单的浅拷贝。
拷贝列表
copy.copy();
只对第一层进行深拷贝,如果列表中还有其他元素,则其他的进行浅拷贝。
deep.copy()
全部进行深拷贝 注意列表的切片list[:]和copy一样属于浅拷贝。
拷贝不可变类型
例如元组
在拷贝主元素和子元素都是不可变类型时,
copy.copy()
copy.deepcopy()
都是拷不动的,拷贝的都是引用。
如果其中子元素有一个是可变类型,即使不可变类型数据为第一层,那么deepcopy就可以对该数据进行深拷贝,而copy还是指向
类的属性
-
xx:公有变量
-
_xx:单前置下划线开头的属性或方法,表示在禁止在模块中导入,
禁止 from yyy import xxx 导入 -
__xx:双前置下划线开头,表示该属性/方法为私有的,使用对象实例化无法直接访问和操作,只能利用特殊方法来操作该属性或方法。
设个私有化的原理是:自动将该变量名改变了,规则是:_类名变量名 -
_xxx_:双前后置下划线,为魔法属性或方法
-
xxx_:单后置下划线,表示避免与关键字相同
import导入模块
import 模块
from yyy import xxx
from yyy import *
import xxx as XXX :起别名避免一个程序中变量和模块名相同
导入模块的顺序
import sys
sys.path
用于查看导入模块时的查找文件的顺序
sys.path.insert(下标,模块路径)
该表导入模块时的搜索路径
导入模块的注意事项
重新加载模块
当一个程序导入了一个模快,但在该模块导入后,这个模块被修改了,这就需要将该模块重新导入。
import xxxx
这样都是不行的,因为在python重复导入模块时只有第一次导入有效
要想重新再导入模块一次要使用
imp模块中reload函数
reload(模块名);
多模块导入事项
导入模块只是定义了一个变量然后指向了那一个导入的地方,并不是实际的
**from yyy import xxx **导入
使用该方式导入模块,只是在该文件中定义了一个全局变量xxx该变量的指向为yyy模块中xxx,如果在该文件中改变了xxx的值并不会改变yyy中的xxx,而是在该文件中将xxx的指向改变了而已。
不过如果xxx是一个列表,对列表进行append和remove操作是可以的,因为该操作不是改变指向
import yyy
该导入方式是导入了该模块的引用,使用yyy.xxx则可以改变值,当其他模块在使用时就会发生改变