== 和is 的区别、深拷贝与浅拷贝、闭包、装饰器、进程、进程池、进程之间通讯、协程、网络编程、socket

== 和 is 的区别:

== 用来判断a 和 b中的内容是否相同
is 用来判断a 和 b内存地址是否相同
python有一个内存优化机制-小整数常量池:-5到256在这里插入图片描述

拷贝

首先明确
可变数据类型(引用数据类型):列表、字典
不可变数据类型(值数据类型):数字类型、字符串类型、元组数据类型、布尔数据类型

拷贝:将a中数据复制到一个新的内存空间,并让b指向这个新创建的内存空间
如果对象是列表嵌套结构,同copy.copy浅拷贝会出问题,但深拷贝不会
所以爬虫时可以使用深拷贝,以防止出现问题
在这里插入图片描述

闭包

闭包的本质就是一个嵌套函数,函数嵌套函数,同时将内部函数作为返回值
在这里插入图片描述
在这里插入图片描述

装饰器

在不修改原本代码的基础上,就可实现验证等功能,其中@w1是代码糖
在这里插入图片描述
总结:装饰器的底层是闭包实现的,它是怎么巧妙的进行实现权限验证呢?
先将f1的指向进行保存,保存到了参数为func这个中。
通过return返回值来修改f1的指向,将f1的指向转到了权限验证的函数中了。
当你在最下面进行调用f1的时候,先验证,再执行func。
在这里插入图片描述

列表生成式

变量名 = [变量 循环生成式 条件]
例如:在这里插入图片描述

列表生成器

将列表生成式的[ ]变成(),要取出其中的值可以用next(a)
在这里插入图片描述
下面的生成器中的值取出时也可以用for循环或者a.–next–()
在这里插入图片描述

迭代器Iterable

迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退

可迭代对象

直接作用于 for 循环的数据类型有以下几种:
一类是集合数据类型,如 list 、 tuple 、 dict 、 set 、 str 等;
一类是 generator ,包括生成器和带 yield 的generator function。
即可以通过for循环的统统都可以称为可以迭代的对象

判断方法:
可以使用 isinstance() 判断一个对象是否是 Iterable 对象
也可以使用 isinstance() 判断一个对象是否是 Iterator 对象
使用前需要from collecting import Iterable
迭代器是可迭代对象,但可迭代对象不一定是迭代器
而若要将可迭代对象变成迭代器可以使用iter()函数

所以
凡是可作用于 for 循环的对象都是 Iterable(可迭代的对象) 类型;
凡是可作用于 next() 函数的对象都是 Iterator(迭代器) 类型
list 、 dict 、 str 等是 Iterable 但不是 Iterator ,不过可以通过 iter() 函数获得一个 Iterator 对象。

functools的使用

本应输出test中的内容,但若不用该函数则会在第三条时输出wrapper中的内容
在这里插入图片描述

进程

并行:任务量小于或是等于cpu的核心数,称这样的多进程为并行。
并发:任务量多于cpu核心数,称这样的多进程为并发
multiprocessing模块就是跨平台版本的多进程模块,提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情
在这里插入图片描述
在主进程执行的同时,利用Process创建一个子进程,实现多任务,主进程总会等待子进程结束后在结束,join()方法则可以等待子进程结束后再继续往下运行,通常用于进程间的同步
在这里插入图片描述

进程池

进程不多时可以手动创建,但若是成千上百个进程,则需使用进程池pool,在创建进程池的时候,可以指定进程数。当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会创建新的进程来执行。
apply_async(func[, args[, kwds]]) :
使用非阻塞方式(所有的进程可以一起干活)调用func(并行执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递给func的参数列表,kwds为传递给func的关键字参数列表;
apple堵塞式添加任务:执行完第一个再去执行第二个。
close():关闭Pool,使其不再接受新的任务;
terminate():不管任务是否完成,立即终止;
join():主进程阻塞,等待子进程的退出,必须在close或terminate之后使用;
在这里插入图片描述
使用进程池的好处是:不用管有多少个进程,程序总会在空闲的时候将多出的进程放进池中继续执行

而且进程中的全局变量是不共享的哦,所以需要用队列Queue来实现进程间的通讯

队列Queue

Queue.qsize():返回当前队列中的消息数
Queue.empty():若队列为空,则返回True
Queue.full():若队列满,则返回True
Queue.get():获取一条消息,并将其从队列中移除,没有可以获取的消息时自动阻塞,可用ctrl+c退出
Queue.get-nowait():获取一条消息,并将其从队列中移除,没有可以获取的消息时自动抛出异常
Queue.put():向队列中放入一条消息,没有可以放入消息位置时自动阻塞,可用ctrl+c退出
Queue.put-nowait():向队列中放入一条消息,没有可以放入消息位置自动抛出异常
在这里插入图片描述
在开启写进程的时候,还没有开启读进程的中间,加join(),相当于进程池中的阻塞,一个子进程执行完在执行另一个

进程池中的Queue

在进程池中需要使用manager.Queue
如果要使用Pool创建进程,就需要使用multiprocessing.Manager()中的Queue()

在这里插入图片描述

线程

线程也是用来完成多任务的一种方式。python的thread模块是比较底层的模块,python的threading模块是对thread做了一些包装的,可以更加方便的被使用。
进程里面套了线程。
进程是资源分配的单位,线程是CPU调度的单位
主线程会等所有子线程结束后再结束
使用方法创建线程:
在这里插入图片描述
使用类创建线程:创建一个类,继承threading.Thread,然后在类中写一个run方法即可
线程的执行顺序是没有先后的,是根据cpu的时间片轮转调度算法算出来的
threading.enumerate()可以查看进程数量哦
对于多线程而言,对全局变量是共享的,而对于多进程来说,对全局变量是不共享的。

在这里插入图片描述
虽然可以共享,但是容易出现资源争抢并出错,所以有以下几种方式避免
1.利用time.sleep()
在这里插入图片描述

2.设置一个变量作为标志
如果该变量值为1说明,任务work1还没有执行完呢,如果值为0说明,任务work1执行完了
在这里插入图片描述
3.互斥锁
当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制
线程同步能够保证多个线程安全访问竞争资源,最简单的同步机制是引入互斥锁
互斥锁为资源引入一个状态:锁定/非锁定。
某个线程要更改共享数据时,先将其锁定,此时资源的状态为“锁定”,其他线程不能更改;直到该线程释放资源,将资源的状态变成“非锁定”,其他的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行写入操作,从而保证了多线程情况下数据的正确性
创建:m = threating.Lock()
锁定:m.acquire()
释放:m.release()
在这里插入图片描述
创建线程时可以有以下参数:
Thead(group = None,target = None,name = None,args = (),kwargs = {})
group:线程组
target:要执行的方法
name:线程名
args/kwargs:要传入方法的参数
多线程一般采用非共享变量,例如局部变量。全局变量在多线程中使用易出现数据错乱的情况,若需修改则要加上互斥锁
若要查看线程名字:threating.current_thread().name
在这里插入图片描述

协程

又称微线程,纤程。英文名Coroutine
协程是在一个进程里面或是一个线程里面,将任务分成了多份,也是完成多任务、并发的一种方式
实现协程的第一种方式:使用过yield关键字,通过生成器
实现协程的第二种方式:使用greenlet完成多任务,但是缺点是还的人工切换
首先pip install greenlet
在这里插入图片描述

实现协程的第三种方式:使用gevent完成多任务,可以实现自主切换,但只有遇到需要耗时的操作才会执行
首先pip install gevent
创建gevent对象时需要用gevent.spawn(方法名,传入方法的参数)
gevent.getcurrent()获取当前协程
gevent.sleep()添加耗时操作
若不想用gevent.sleep ()则需要先gevent.monkey.patch_all(),再用time.sleep()耗时
在这里插入图片描述
同时,所有的join()操作,可以用以下方式代替在这里插入图片描述
接下来使用协程制作一个图片下载器:
在这里插入图片描述

网络编程

让在不同的电脑上的软件能够进行数据传递,即进程之间的通信
tcp-ip协议:计算机都遵守的网络通信协议,常见的四层:应用层-传输层-网络层(网际层)-链路层(网络接口层)
端口是通过端口号来标记的,端口号只有整数,范围是从0到65535
知名端口是众所周知的端口号,范围从0到1023
80端口分配给HTTP服务
21端口分配给FTP服务
动态端口的范围是从1024到65535
之所以称为动态端口,是因为它一般不固定分配某种服务,而是动态分配。
动态分配是指当一个系统进程或应用程序进程需要网络通信时,它向主机申请一个端口,主机从可用的端口号中分配一个供它使用。
当这个进程关闭时,同时也就释放了所占用的端口号。
每一个IP地址包括两部分:网络地址和主机地址

网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)

socket

socket(简称 套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:
它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的
首先import socket后
用socket.socket(AddressFamily,Type)创建
① Address Family:其中可以选择 AF_INET(用于 Internet 进程间通信) 或者 AF_UNIX(用于同一台机器进程间通信),实际工作中常用AF_INET
② Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)

套接字socket是一个类,所以将来在使用的时候返回值就是一个对象,这个对象拥有发送网络数据和接收网络数据的功能,这样的对象称之为套接字。
在这里插入图片描述
NetAssist.ext软件是用来协助我们完成网络请求的
在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值