标签:requests 互斥锁 from 原子操作 三次 隔离机制 gil 递归 网线
编译型:计算机运行前将程序全部编译后才运行的语言,运行速度快,开发效率低
解释型:计算机通过虚拟机边编译边运行的语言,云行速度慢,开发效率高
1.由字母,数字,下划线组成
2.禁止以数字开头
3.禁止使用python中的关键字及内置函数的名字
4.不建议使用中文和拼音
5.具有可描述性
6.区分的大小写
7.推荐写法:驼峰体: AgeOfOldboy = 56 下划线:age_of_oldboy = 56
8.不建议太长
break:跳出当前循环
continue:伪装成循环体中的最后一行代码,跳出当前循环,进行下次循环
相同点:他们以下的的代码都不执行
is 是判断两边的内存地址是否相同
== 是判断两边的值(内容)是否相同
1字节等于8位
pass 站位,为了保持程序结构的完整性
type 是判断数据类型(获取对象从属于的类)
id 是判断内存地址
数字:0 字符串:"" 列表:[] 字典:{} 集合:set() 元组:() 布尔值:False
其他:None (3<2)
赋值:多个变量名指向同一个内存地址,一个变量对其操作,其他变量查看时都变动
浅拷贝:只拷贝第一层空间,即开辟新的内存地址,不可变数据和可变数据共用
深拷贝:开辟一块新的内存空间,不可变数据共用,可比那数据重新开辟空间
小数据支持:
字符串:纯字母和数字的时候长度任意,内存地址相同。
Python36纯字母和数字乘法总长度 <= 20 内存地址相同。
Python37纯字母和数字乘法总长度 <= 4096 内存地址相同。
中文和特殊符号乘法的时候只能乘以 0 内存地址相同
数字:-5 ~ 256
布尔值:True False
代码块支持:
字符串:?定义字符串的时候内容,长度任意内存地址相同。
字符串进行乘法的时候总长度 <=20 内存地址相同。
中文,特殊符号 乘法的时候只能乘以1或 0
数字:相同的数字内存地址相同
布尔值:相同的内存地址相同
1.不断地调用自己本身
2.有明确的终止条件
1.可以当做值被赋值给变量
2.当做元素存放在容器中
3.当作函数的参数
4.当作函数的返回值
定义:以功能为导向,一个函数封装一个功能
1.减少重复代码
2.提高代码的可读性
return 返回值
return 返回一个内容(就是内容本身) 可以返回任意类型
return 返回多个内容,以元组的形式返回
return 终止函数 ,切记不能终止循环
return 下方的代码不执行
return 不写返回值或者没有return就返回None
return 将内容返回给了函数的调用者
形参:函数定义时的参数,位置参数>默认参数>混合参数
实参:函数调用时的参数,位置参数>关键字参数>混合参数
传参:将实参传给形参的过程
def func(a,*args,sex='男',c, **kwargs):
print(a)
print(args)
print(sex)
print(c)
print(kwargs)
func(1,c=4,name='alex') #c就是仅限关键字参数
*args 动态位置参数,可以接受0个或多个位置参数,返回元组,不传值时()
*kwaargs 动态关键字参数,可以接受0个或多个关键字参数,返回字典,不传值时{}
a,*b,c = [1,2,3,4,5,6]
print(a,b,c) #1 [2, 3, 4, 5] 6
a,*b,c = [1,6]
print(a,b,c) #1 [] 6
a, *b = range(1,7)
print(a,b) #1 [2, 3, 4, 5, 6]
a, *b = (1,2,3,4)
print(a,b) #1 [2, 3, 4]
内置命名空间:存储的是内置函数与模块等
全局命名空间:当前py文件,存放的是变量与值的对应关系
局部命名空间:函数运行时,在内存中开辟一个临时的名称空间,存放的是函数内部的变量与值的对应关系,函数结束后就消失
加载顺序:内置命名空间 > 全局名称空间 > 局部命名空间
取值顺序:局部命名空间 > 全局命名空间 > 内置命名空间
全局作用域:内置命名空间 + 全局命名空间
局部作用域:局部命名空间
locals() 返回是当前局部变量的深拷贝,修改locals() 中变量值的时候,实际上对于原变量本身是没有任何影响的,(全局中和globals()用法相同)
而globals()返回的是全局变量的字典,修改其中的内容,值会真正的发生改变
global:在函数内部修改全局空间的变量对应的值;声明一个全局变量
nonlocal:在嵌套函数中,修改局部空间的变量值,只修改离它最近的一层,最近的一层没有变量继续向上找,直到找到最外层函数,但完全不涉及全局变量
globals():print(globals()),返回一个字典,无论在函数内部打印还是在外部打印,结果都是全局变量与值的关系的字典,glocals()的结果共用一个空间,无论在哪里,只要字典中的值改变了,这个结果就会改变
locals():print(locals()),返回一个字典,结果是当前空间变量与值的关系的字典,如果没有变量就是空字典,如果在局部空间中,locals()结果中改变值,局部空间中的变量值不会改变(深拷贝),如果在全局空间,结果和globals()的结果相同,这时候改变字典中的值,全局空间的值就会改变.
b = 5
def test2():
a = 1
locals()["a"] = 2 # 只修改字典的值,
print("第一a>>",a) # 与a无关了,深拷贝
globals()["b"] = 6 # 修改了b的值,共用空间
print("第一b>>",b)
if __name__ == '__main__':
test2()
print("第二b>>",b)
locals()["b"] = 3 # 修改了b的值,共用空间
print("第三b>>",b)
b = 5
def test2():
a = 1
print(locals(), end="\n" * 2) #当前空间,有一个变量
def func():
print(locals(),end="\n"*2) #当前空间,空字典
print(globals(),end="\n"*2) #全局空间
func()
if __name__ == '__main__':
test2()
print(locals(),end="\n"*2) #当前空间,全局空间
print(globals(),end="\n"*2) #全局空间
在嵌套函数中,内层函数对外层函数的变量(非全局,非本层)的调用
作用:保存局部信息不被销毁,保证数据的安全性
应用:
1.可以保存一些非全局变量但是不易被销毁、改变的数据。
2.装饰器
os,sys,hashlib,collections,re,time,datetime,random,socket,threading,logging,Queue,json,pickle
Requests,MySQL,Django,Event,gevent
序列化模块就是将一个常见的数据结构转化成一个特殊的序列,并且这个特殊的序列还可以反解回去。它的主要用途:文件读写数据,网络传输数据
添加自定义模块路径
1.自动执行__new__方法开辟并返回一个对象空间
2.自动执行类中的__init__方法,并将这个对象空间(内存地址)传给__init__方法的第一个位置参数self
3.在__init__方法中通过self给对象空间封装属性
1.继承:单继承和多继承,子承父业,它可以使用现有类的所有功能,并在无需重新编 写原来的类的情况下对这些功能进行扩展
2.封装:就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信 的类或者对象操作,对不可信的进行信息隐藏
3.多态:一个变量,多种形态,指一个类实例的相同方法在不同情形有不同表现形式。 多态机制使具有不同内部结构的对象可以共享相同的外部接口
定义:就是一类相似功能函数的集合
使代码更清晰化,更合理化
拥有上帝视角看问题,类其实就是一个公共模板,对象就是从具体的模板实例化出来的
看起来像鸭子,它就是鸭子,对相同的功能定义了相同的名字,这样方便开发,两种方法互称鸭子类型,例如,list,tuple,str都有index方法,这种就是统一了规范,互为鸭子模型
__init__初始化,给对象封装属性
__new__构造方法,新生成一个对象
__del__析构方法,当对象在内存中被释放时,触发执行
__len__计算长度
__hash__判断是否可哈希
__str__返回内容
__repr__原形毕露,返回其原始值
__call__对象+()触发执行call方法
__eq__同一类的两个实例比较时会触发
__item__对对象进行类似字典的操作就会触发该方法
__enter__上下文管理,进入时
__exit__上下文管理,出来时
class A:
a = None
def __new__(cls, *args, **kwargs):
if not cls.a:
cls.a = object.__new__(cls)
return cls.a
obj1 = A()
print(obj1)
obj2 = A()
print(obj2)
isinstance(a,b):判断a是否是b类或者b类的派生类的实例化对象
issubclass(a,b):判断a类是否是b类或者b类的派生类的派生类
self传入的是一个类的实例化对象
cls传入的是一个类名
都是位置参数,都是隐形传参
其实就是父类对子类进行约束
1.使用抽象类和抽象方法,由于该方案来源是Java和c#,所以使用频率很少
2.使用人为抛出异常的方案,只要子类用到父类的方法,就抛出错误
跳过本类
单继承时,按照深度优先原则,查找下一类
多继承时,严格按照对象从属于类的mro顺序查找下一类
具有__enter__ 和 __exit__ 方法
object是type元类的实例化对象 print(isinstance(object,type))
type类是object类的派生类 print(issubclass(type,object))
作用:通过字符串的形式操作对象相关的属性
hasattr 检测是否存在
getattr 获取
setattr 设置
delattr 删除
# 第一种方法callable,返回True有可能调用失败,但是返回False,那绝对不能调用
def func():
?print(1)
func()
print(callable(func))
# 第二种方法,判断对象类型是否属于FunctionType,若为True,则可调用
from types import FunctionType
print(isinstance(func,FunctionType))
# 第三种方法,判断对象是否实现__call__方法
print(hasattr(func,'__call__'))
# 静态方法属于函数,类方法和实例方法分别依赖于类和对象,所以他们是method,其余我们自己定义的都是函数,函数就可调用
#若想让一个类的实例化对象可调用,可在类中定义__call__方法,即可实现
经典类:在python2.2之前,一直使用的是经典类,经典类在基类的根什么都不写,采用深度优先遍历方案
新式类:在Python2.2之后出现了新式类,新式类的特点是基类的根是object类,python3中使用的都是新式类,默认继承object类,采用c3算法遍历原则,mro序列
函数是显性传参,不依赖于类和对象
方法是隐形传参,依赖于类和对象
类中的静态方法(@staticmethod),是函数
类中的类方法(@classmethod),是方法
from types import FuctionType,MethodType (函数类,方法类)
python中一切皆对象,类在某种意义上也是一个对象,python中自定义的类,以及大多数内置类,str,dict等,都是type元类实例化得来的
python中一切皆对象,函数在某种意义上也是一个对象,它是从FunctionType这个类实例化出来的
python中一切皆对象,方法在某种意义上也是一个对象,方法这个对象是从MethodType这个类实例化出来的
property,将方法伪装成属性,调用时看起来像是调用类或者对象的属性,其实调用的是方法
优点:看起来更合理,遵循了统一访问原则
由于伪装成了属性,属性可以增删改查,所以配套有了setter 修改属性 deleter 删除属性(都是伪装的,执行时调用此方法)
class Foo:
@property
def AAA(self):
print('get的时候运行我啊')
@AAA.setter
def AAA(self,value):
print('set的时候运行我啊')
@AAA.deleter
def AAA(self):
print('delete的时候运行我啊')
#只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
obj = Foo()
obj.AAA
obj.AAA = 'aaa'
del obj.AAA
类的私有属性;类的私有方法;对象的私有属性;对象的私有方法(对象的方法不清楚,可能是函数当做对象,他自己的方法)
只能在类的内部使用
异常:异常发生之后,程序就中断了
异常处理:代码发生异常时,通过某种手段不让程序中断,合理地跳过去
原因:增强用户的体验感;使代码更有健壮性,容错性
注意:1.异常处理慎重使用,因为比较消耗性能
2.异常处理的所包含的代码区域尽量精简,不要把整段代码都写入try,而是针对个别可能会抛出异常的位置进行异常处理
finally不管出不出现异常都执行,如果有异常,在异常出现之前执行
用途:1. 关闭文件句柄,关闭数据库链接,保证数据安全
2.函数return之前能够执行finally代码
3.break之前可以执行finally
操作系统位于计算机硬件和软件之间,本质也是一个软件,就是一个协调,管理和控制计算机硬件资源和软件资源的控制程序
作用:1.隐藏了丑陋的硬件调用接口,为程序员提供简单清晰的应用程序
2.将应用程序对硬件的竞态请求变的有序化
3.当多个进程抢占一个CPU资源时,操作系统将你的执行变的合理有序
区别:操作系统由硬件保护,不能被用户修改
1.空间上的复用:将内存分区域,一个内存可以同时加载多个进程(但是还没有做到真正意义上的隔离,各个软件之间可以互相访问,一个软件中病毒都会被传染,没有真正物理隔离)
2.时间上的复用:实现CPU在多个进程之间来会切换,并且保留状态(当进程遇到io阻塞或者长时间运行时,操作系统会将此进程挂起,保留状态,将CPU强行切换到另一个进程)
正在进行的一个程序或者说一个任务就是进程,进程是计算机中最小的资源分配单位,而负责执行任务的是CPU
1.运行,CPU执行此进程
2.阻塞,遇到io阻塞
3.就绪,结束阻塞,CPU在运行别的进程
程序仅仅是一堆代码而已,进程指的是程序的运行过程
1.应用层,网络服务与最终用户的一个接口,常见协议:HTTP,FTP等
2.表示层,主要是对接收的数据进行解释,压缩和解压缩等,即把计算机能够识别的东西转化成人能够识别的东西(如图片,声音等)(五层协议合并到应用层)
3.会话层,通过传输层建立数据传输通路,在系统之间发起会话或者接受会话请求
4.传输层,定义传输数据的协议端口号,以及流控和差错校验,常见协议TCP,UDP
5.网络层,进行逻辑地址寻址,实现不同网络之间的路径选择,IP,ARP,路由协议
6.数据链路层,主要是将从物理层接收的数据进行Mac地址的封装和解封,对比特流进行分组(以太网协议)
7.物理层,建立,维护,断开物理连接,由网线,光纤等一系列物理介质组成,发送比特流
TCP:可靠的,面向连接的协议(通讯时必须先建立连接),传输效率低,面向字节流,如浏览器,文件传输程序
UDP:不可靠的,无连接的服务(通信时不用建立连接),传输效率高,视频,语音软件
mac地址:计算机网卡上记录的独一无二的地址
ARP协议:通过对方的ip地址获取到对方的mac地址
IP协议: 确定局域网(子网)的位置
端口协议: 确定计算机软件在计算机的位置
以太网协议: 对比特流进行合理的分组
路由协议:确定网络路径
串行:所有的任务一个一个的完成
并行:一个CPU完成多个任务,看起来像是同时完成的
并发:多个CPU执行多个任务,真正的同时完成
C/S:基于客户端与服务端的架构,这种架构是从用户层面来划分的,这里的客户端一般泛指客户端的应用程序EXE,程序需要先安装后,才能在用户的电脑上运行,对用户的电脑操作系统环境依赖性较大.qq,微信
优点:个性化设置,响应速度快
缺点:开发.维护成本高,占用空间,用户固定
B/S:基于浏览器和服务端的架构,这种架构是从用户层面来划分的,只是这个客户端不需要大家去安装什么应用程序,只需在浏览器上通过HTTP请求服务端相关的资源,客户端就能进行正常的访问,谷歌浏览器,火狐浏览器
优点:开发.维护成本低,用户不固定
缺点:功能单一,没有个性化设置,响应速度相对慢
输入缓冲区,输出缓冲区. 存储少量数据,避免网络不稳,造成你传输数据时的卡顿,保持相对平稳,稳定
1.接收方没有及时接收缓冲区的包,造成多个包接收(客户端发送了一段数据,服务端只收了一小部分,服务端下次再收的时候还是从缓冲区拿上次遗留的数据,产生粘包)
2.发送端需要等缓冲区满才发送出去,造成粘包(发送数据时间间隔很短,数据也很小,会合到一起,产生粘包)
1.Windows环境下,开启进程必须在__name__测试端口下进行
2.args传的值必须以元组形式,target,args名称不可改变(与函数不同)
3.进程消耗大(耗时间),主进程速度快,p.start()只是操作系统发出一个开辟一个子进程的信号,就继续执行主进程
4.子进程复制主进程if之上的内容,空间在内存中是独立的,修改与否与主进程无关
5.进程的name默认值为Process-1,可以实例化时name="自定义",也可以p.name = "自定义"
1.必须写上继承Process类
2.p = Process()时如果没传值,name默认继承父类,默认值为 类名-1
3.如果传值了name,构建__init__方法,必须继承父类super()的init方法,因为进程init方法还有其他参数,可以只覆盖name的
4.约束,必须有run方法,否者执行父类的,什么都没有,结果只执行了主进程
pid是进程在内存中的唯一标识
在cmd终端输入tasklist查询所有进程的pid
在cmd终端输入tasklist|findstr python查询pycharm中多个进程的pid
在cmd终端输入tasklist|findstr pycharm查询主进程的pid
(在pycharm文件未关闭的前提下才可以找到time.sleep(50))
代码中获取:os.getpid() 本进程
os.getppid() 父(主)进程
无论是可变还是不可变,主进程都不变,空间隔离了
#一个进程下的调用函数
name = "alex"
def task():
global name
name = "刚哥"
if __name__ == '__main__':
task()
print(name)
#多个进程空间隔离
from multiprocessing import Process
import time
lst = [1,2]
def task():
lst.append(3)
print(f"子:{lst}")
if __name__ == '__main__':
p = Process(target=task)
p.start()
print(f"主:{lst}")
共同点:都可以把并发变成串行,保证了顺序
不同点:join人为设定顺序,lock让所有进程公平竞争,保证了公平性
join阻塞,阻止join以下的代码执行,直到阻塞结束
代码优化
if __name__ == '__main__':
lst = []
for i in range(3):
p = Process(target=task,args=(i,)) #p是对象
lst.append(p)
p.start()
for t in lst:
t.join()
print("==>主开始")
#优化串行
if __name__ == '__main__':
for i in range(3):
p = Process(target=task,args=(i,)) #p是对象
p.start()
p.join()
print("==>主开始")
p.terminate() 杀死子进程,由于开启子进程需要时间,杀死在摇篮
p.is_alive() 返回Ture or False,判断子进程是否活着,进行中才为Ture
守护进程:子进程守护主进程,只要主进程结束,子进程就结束了(主进程结不结束与子进程无关)(注意主线程的区别)
p.daemon = Ture,必须在子进程开启之前(p.start()之前)设置,否则报错
僵尸进程:子进程结束后,在被主进程回收之前,都会进入僵尸状态
孤儿进程:主进程因为某种原因结束了,但子进程还在运行中,这些子进程就成了孤儿进程,这些子进程会被init进程回收
僵尸进程是有害的,如果主进程不对僵尸进程进行回收,就会有大量的僵尸进程产生,会占用内存,每个僵尸进程都会占用pid号
1.基于文件通信
2.基于队列通信
3.基于管道通信
lock互斥锁用的是同一把锁,未上锁时,并行或并发抢锁,上锁后串行,锁释放后公平竞争,连续两次产生死锁现象,整个过程中是同一把锁,但是因为工厂原因导致id不同
from multiprocessing import Queue
q = Queue(2)
q.put()#超过两个2个阻塞
print(q.get()) #超过两个2个阻塞
参数:block=False ,阻塞时报错
timeout=3 ,阻塞3秒后报错
生产者:产生数据的
消费者:接收数据做进一步的处理
容器:队列(作用:起到缓冲的作用,平衡生产力和消费力,解耦)
lock锁:互斥锁,在一个进程或者线程中只能连续acquire一次,否则会发生死锁现象
GIL锁:全局解释器锁,cpython解释器自带的,保证了同一个进程的多个线程同一时刻只能有一个线程访问
递归锁:RLock,同一把锁,引用一次计数+1,释放一次计数-1,只要计数不为0,其他线程进程就抢不到,能够解决死锁现象
优缺点:lock是自定义的锁,保证进程中的数据安全,容易出现死锁现象
gil锁是解释器自带的锁,保证了解释器的资源数据的安全,单进程的多线程不能利用多核
socket是处于应用层与传输层之间的抽象层,它是一组操作起来非常简单的接口(接受数据),此接口接收数据之后,交由操作系统
如果直接与操作系统数据交互非常麻烦,繁琐,socket对这些繁琐的操作高度的封装简化
进程:正在进行的一个过程或者说一个任务,即在内存中开启一个进程空间,然后将主进程的所有的资源数据复制一份,然后调用线程去执行代码
线程:在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程
1. 进程是资源单位, 线程是执行单位
2. 开启进程的开销非常大,比开启线程的开销大很多
3. 开启线程的速度非常快.要快几十倍到上百倍
4. 同一进程中线程线程之间可以共享数据,进程与进程之间需借助队列等方法实现通信
5.线程之间的pid(这个进程的)相同,进程与进程之间的pid不同
守护线程:子线程守护主线程,主线程结束了守护进程就结束了,主线程是等待所有的非守护子线程结束之后才结束
也是一种锁, 控制并发数量
多进程可以利用多核,当计算密集型时多条线同时进行,而多线程不能利用多核,只能多个线程之间来回切换,数量级大时,来回切换浪费时间
1.阻塞:程序运行时遇到了io,程序挂起,CPU被操作系统切走
2.非阻塞:程序没有遇到io,或遇到IO但是我通过某种手段(协程),让cpu强行运行我的程序
3.同步:(发布任务的角度)提交一个任务,自任务开始运行直到此任务结束(可能有IO),返回一个返回值之后,我在提交下一个任务
4.异步:(发布任务的角度)一次提交多个任务,然后我就直接执行下一行代码.
1. 将所有的任务的结果统一回收
2. 完成一个任务,返回一个结果
按顺序接收每个任务的结果,进行下一步处理
事务:由一组sql语句组成的逻辑处理单元.
原子性(Atomicity):事务是一个原子操作单元。在当时原子是不可分割的最小元素,其对数据的修改,要么全部成功,要么全部都不成功。
一致性(Consistent):事务开始到结束的时间段内,数据都必须保持一致状态。
隔离性(Isolation):数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的"独立"环境执行。
持久性(Durable):事务完成后,它对于数据的修改是永久性的,即使出现系统故障也能够保持。
标签:requests 互斥锁 from 原子操作 三次 隔离机制 gil 递归 网线
原文地址:https://www.cnblogs.com/lvweihe/p/11736101.html