---恢复内容开始---
思想
主要的思想:如果一个变量自己有某种方法,而你想在不改变调用方式的前提下,希望可以点出它本身不存在的方法,就要想到用 类 封装的思想 , 将这个变量,改变为一个类的对象,在类中增加你需要的方法例如:
# lst1= [1,2,3,4]#有append 的功能# lst2= [1,2,3,4]#有append 的功能# lst3= [1,2,3,4]#有append 的功能# lst4= [1,2,3,4]#有append 的功能# l = [lst1,lst2,lst3,lst4]# for i in l:# i.append(6)#很明显都可以执行,# # i.eat() 明显直接飘红了,怎样在我不改变调用方式的前提下,可以将该功能实现:
class Foo(object): def __init__(self,lst,eat): self.eat = eat self.lst = lst def append(self,n): print(n+1) self.lst.append(3) lst1= [1,2,3,4] #有append 的功能 lst2= [1,2,3,4] #有append 的功能 lst3= [1,2,3,4] #有append 的功能 lst4= [1,2,3,4] #有append 的功能 lst1_obj = Foo(lst1,"苹果") lst2_obj = Foo(lst2,"橘子") lst3_obj = Foo(lst3,"xiangjiao") lst4_obj = Foo(lst4,"jiaozi") l = [lst1_obj,lst2_obj,lst3_obj,lst4_obj] for i in l: i.append(3)#很明显都可以执行, print(i.eat) #明显直接飘红了,怎样在我不改变调用方式的前提下,可以将该功能实现:
# 你写的代码:7000w v = [ [11,22], # 每个都有一个append方法 [22,33], # 每个都有一个append方法 [33,44], # 每个都有一个append方法 ] # 王思聪 for item in v: print(item.append) 之后: class Foo(object): def __init__(self,data,girl): self.row = data self.girl = girl def append(self,item): self.row.append(item) v = [ Foo([11,22],‘雪梨‘), # 每个都有一个append方法 Foo([22,33],‘冰糖‘), # 每个都有一个append方法 Foo([33,44],‘糖宝‘), # 每个都有一个append方法 ] for item in v: print(item.append) item.girl
一 IO多路复用
1 Io多路复用的作用:监测多个socket 是否发生变化(是否已经发生成功连接,是否读取到数据)
操作系统监测socket是否发生变化,有三种模式:
select: 最多监听1024,循环监测
poll;不限制监听socket个数,还是循环监测
epoll:不限制监听个数,回调方式监测(边缘触发)
2 异步非阻塞:
阻塞:不等待.
比如创建socket对某个地址 进行 connect 获取接受数据,都会默认阻塞
如果设置setblocking(False),以上两个过程就不再等待,但是会报BlockingIOError的错误,只要捕获就行
异步:,通知,执行完成之后自动执行回调函数或自动执行某些操作(通知)。
比如做爬虫中向某个地址baidu.com发送请求,当请求执行完成之后自执行回调函数。
3 同步 阻塞
同步 ;按顺序执行
阻塞:等
普通的单进程单线程
import socket import requests # 方式一 ret = requests.get(‘https://www.baidu.com/s?wd=alex‘) # 方式二 client = socket.socket() # 百度创建连接: 阻塞 client.connect((‘www.baidu.com‘,80)) # 问百度我要什么? client.sendall(b‘GET /s?wd=alex HTTP/1.0\r\nhost:www.baidu.com\r\n\r\n‘) # 我等着接收百度给我的回复 chunk_list = [] while True: chunk = client.recv(8096) if not chunk: break chunk_list.append(chunk) body = b‘‘.join(chunk_list) print(body.decode(‘utf-8‘))
解决并发----单线程
for item in key_list: ret = requests.get(‘https://www.baidu.com/s?wd=%s‘ %item) # 方式二 def get_data(key): # 方式二 client = socket.socket() # 百度创建连接: 阻塞 client.connect((‘www.baidu.com‘,80)) # 问百度我要什么? client.sendall(b‘GET /s?wd=alex HTTP/1.0\r\nhost:www.baidu.com\r\n\r\n‘) # 我等着接收百度给我的回复 chunk_list = [] while True: chunk = client.recv(8096) if not chunk: break chunk_list.append(chunk) body = b‘‘.join(chunk_list) print(body.decode(‘utf-8‘)) key_list = [‘alex‘,‘db‘,‘sb‘] for item in key_list: get_data(item)
解决并发-------多线程
import threading key_list = [‘alex‘,‘db‘,‘sb‘] for item in key_list: t = threading.Thread(target=get_data,args=(item,)) t.start()
解决并发-----单线程 +io多路复用
先了解一下setblocking
import socket client = socket.socket() client.setblocking(True) # 将原来阻塞的位置变成非阻塞(报错),改成 false即变成阻塞的了 # 百度创建连接: 阻塞 try: client.connect((‘www.baidu.com‘,80)) # 执行了但报错了 except BlockingIOError as e: pass # 检测到已经连接成功 # 问百度我要什么? client.sendall(b‘GET /s?wd=alex HTTP/1.0\r\nhost:www.baidu.com\r\n\r\n‘) # 我等着接收百度给我的回复 chunk_list = [] while True: chunk = client.recv(8096) # 将原来阻塞的位置变成非阻塞(报错) if not chunk: break chunk_list.append(chunk) body = b‘‘.join(chunk_list) print(body.decode(‘utf-8‘))
普通版本---单线程 +io 基于事件循环实现的异步非阻塞框架
import socket import select client1 = socket.socket() client1.setblocking(False) # 百度创建连接: 非阻塞 try: client1.connect((‘www.baidu.com‘,80)) except BlockingIOError as e: pass client2 = socket.socket() client2.setblocking(False) # 百度创建连接: 非阻塞 try: client2.connect((‘www.sogou.com‘,80)) except BlockingIOError as e: pass client3 = socket.socket() client3.setblocking(False) # 百度创建连接: 非阻塞 try: client3.connect((‘www.oldboyedu.com‘,80)) except BlockingIOError as e: pass socket_list = [client1,client2,client3] conn_list = [client1,client2,client3] while True: rlist,wlist,elist = select.select(socket_list,conn_list,[],0.005) # wlist中表示已经连接成功的socket对象 for sk in wlist: if sk == client1: sk.sendall(b‘GET /s?wd=alex HTTP/1.0\r\nhost:www.baidu.com\r\n\r\n‘) elif sk==client2: sk.sendall(b‘GET /web?query=fdf HTTP/1.0\r\nhost:www.sogou.com\r\n\r\n‘) else: sk.sendall(b‘GET /s?wd=alex HTTP/1.0\r\nhost:www.oldboyedu.com\r\n\r\n‘) conn_list.remove(sk) for sk in rlist: chunk_list = [] while True: try: chunk = sk.recv(8096) if not chunk: break chunk_list.append(chunk) except BlockingIOError as e: break body = b‘‘.join(chunk_list) # print(body.decode(‘utf-8‘)) print(‘------------>‘,body) sk.close() socket_list.remove(sk) if not socket_list: break
高级版本的 并发 -----单线程+Io
import socket import select class Req(object): def __init__(self,sk,func): self.sock = sk self.func = func def fileno(self): return self.sock.fileno() class Nb(object): def __init__(self): self.conn_list = [] self.socket_list = [] def add(self,url,func): client = socket.socket() client.setblocking(False) # 非阻塞 try: client.connect((url, 80)) except BlockingIOError as e: pass obj = Req(client,func) self.conn_list.append(obj) self.socket_list.append(obj) def run(self): while True: rlist,wlist,elist = select.select(self.socket_list,self.conn_list,[],0.005) # wlist中表示已经连接成功的req对象 for sk in wlist: # 发生变换的req对象 sk.sock.sendall(b‘GET /s?wd=alex HTTP/1.0\r\nhost:www.baidu.com\r\n\r\n‘) self.conn_list.remove(sk) for sk in rlist: chunk_list = [] while True: try: chunk = sk.sock.recv(8096) if not chunk: break chunk_list.append(chunk) except BlockingIOError as e: break body = b‘‘.join(chunk_list) # print(body.decode(‘utf-8‘)) sk.func(body) sk.sock.close() self.socket_list.remove(sk) if not self.socket_list: break def baidu_repsonse(body): print(‘百度下载结果:‘,body) def sogou_repsonse(body): print(‘搜狗下载结果:‘, body) def oldboyedu_repsonse(body): print(‘老男孩下载结果:‘, body) t1 = Nb() t1.add(‘www.baidu.com‘,baidu_repsonse) t1.add(‘www.sogou.com‘,sogou_repsonse) t1.add(‘www.oldboyedu.com‘,oldboyedu_repsonse) t1.run()
二 协程 协程不是真实存在的 是程序员为了提高并发效率,开创的
协程 进程,操作系统中存在; 线程,操作系统中存在; 协程,是由程序员创造出来的一个不是真实存在的东西; 协程:是微线程,对一个线程进程分片,使得线程在代码块之间进行来回切换执行,而不是在原来逐行执行。 注意:单纯的协程无用 协程 + 遇到IO就切换 => 牛逼起来了 pip3 install gevent 总结: 1. 什么是协程? 协程也可以称为“微线程”,就是开发者控制线程执行流程,控制先执行某段代码然后再切换到另外函执行代码...来回切换。 2. 协程可以提高并发吗? 协程自己本身无法实现并发(甚至性能会降低)。 协程+IO切换性能提高。 3. 进程、线程、协程的区别? 4. 单线程提供并发: - 协程+IO切换:gevent - 基于事件循环的异步非阻塞框架:Twisted
协程定义
import greenlet def f1(): print(11) gr2.switch() print(22) gr2.switch() def f2(): print(33) gr1.switch() print(44) # 协程 gr1 gr1 = greenlet.greenlet(f1) # 协程 gr2 gr2 = greenlet.greenlet(f2) gr1.switch()
greenlet
from gevent import monkey monkey.patch_all() # 以后代码中遇到IO都会自动执行greenlet的switch进行切换 import requests import gevent def get_page1(url): ret = requests.get(url) print(url,ret.content) def get_page2(url): ret = requests.get(url) print(url,ret.content) def get_page3(url): ret = requests.get(url) print(url,ret.content) gevent.joinall([ gevent.spawn(get_page1, ‘https://www.python.org/‘), # 协程1 gevent.spawn(get_page2, ‘https://www.yahoo.com/‘), # 协程2 gevent.spawn(get_page3, ‘https://github.com/‘), # 协程3 ])
gevent
def f1(): print(11) yield print(22) yield print(33) def f2(): print(55) yield print(66) yield print(77) v1 = f1() v2 = f2() next(v1) # v1.send(None) next(v2) # v1.send(None) next(v1) # v1.send(None) next(v2) # v1.send(None) next(v1) # v1.send(None) next(v2) # v1.send(None)
yield 实现的协程
import socket import select class Req(object): def __init__(self,sk,func): self.sock = sk self.func = func def fileno(self): return self.sock.fileno() class Nb(object): def __init__(self): self.conn_list = [] self.socket_list = [] def add(self,url,func): client = socket.socket() client.setblocking(False) # 非阻塞 try: client.connect((url, 80)) except BlockingIOError as e: pass obj = Req(client,func) self.conn_list.append(obj) self.socket_list.append(obj) def run(self): while True: rlist,wlist,elist = select.select(self.socket_list,self.conn_list,[],0.005) # wlist中表示已经连接成功的req对象 for sk in wlist: # 发生变换的req对象 sk.sock.sendall(b‘GET /s?wd=alex HTTP/1.0\r\nhost:www.baidu.com\r\n\r\n‘) self.conn_list.remove(sk) for sk in rlist: chunk_list = [] while True: try: chunk = sk.sock.recv(8096) if not chunk: break chunk_list.append(chunk) except BlockingIOError as e: break body = b‘‘.join(chunk_list) # print(body.decode(‘utf-8‘)) sk.func(body) sk.sock.close() self.socket_list.remove(sk) if not self.socket_list: break
基于事件循环的异步非阻塞自己写的 ---名字叫 emma---
from emma import Nb def baidu_repsonse(body): print(‘百度下载结果:‘,body) def sogou_repsonse(body): print(‘搜狗下载结果:‘, body) def oldboyedu_repsonse(body): print(‘老男孩下载结果:‘, body) t1 = Nb() t1.add(‘www.baidu.com‘,baidu_repsonse) t1.add(‘www.sogou.com‘,sogou_repsonse) t1.add(‘www.oldboyedu.com‘,oldboyedu_repsonse) t1.run()
使用 emma
---恢复内容结束---
原文地址:https://www.cnblogs.com/lxx7/p/9642051.html
时间: 2024-09-30 22:46:26