共计 2408 个字符,预计需要花费 7 分钟才能阅读完成。
一. 迭代器
什么是迭代器?迭代器是一个能够记住遍历的地位的对象。
迭代器对象从汇合的第一个元素开始拜访,直到所有的元素被拜访完完结,它只能往前进行,不能后退。
什么是可迭代(可迭代对象)?
- 1. 遵循了可迭代协定的对象
-
2. 可迭代协定
- 实现 iter()办法,并返回的 Iterator 对象自身
- 实现 next()办法,当 next()办法被调用,返回下一个值,直到没有值能够拜访。
list、tuple 等都是可迭代对象,咱们能够通过 iter()函数获取这些可迭代对象的迭代器,之后应用 next()函数来获取下一条数据。iter()函数实际上就是调用了__iter_
In [5]: list_demo = [i for i in range(10)] | |
In [6]: iter_list = iter(list_de) | |
In [7]: iter_list = iter(list_demo) | |
In [8]: next(iter_list) | |
Out[8]: 0 | |
In [9]: next(iter_list) | |
Out[9]: 1 | |
In [10]: next(iter_list) | |
Out[10]: 2 |
二. 生成器
什么是生成器?
咱们应用列表时,列表是曾经定义好的数据,例如 [1, 2, 3, 4, 5, 6, 7, 8], 这个能够按照某种算法推算出后续元素,是否能够不创立整个列表,而是遍历循环时,依据算法推算出元素而后应用呢,这样就能够节俭大量空间,实现了这个需要的就是生成器(Generator),实质还是迭代器,然而非凡的迭代器。
生成器是一类非凡的迭代器。
生成器和一般函数的区别是应用 yield,而不是 return 返回值。
- 应用含推导式的 () 定义生成器
In [14]: list_demo = [i for i in range(10)] | |
In [15]: type(list_demo) | |
Out[15]: list | |
In [16]: generator_demo = (i for i in range(10)) | |
In [17]: type(generator_demo) | |
Out[17]: generator |
- 应用函数来实现
def a(): | |
for x in range(3): | |
print(x) | |
yield | |
m = a() | |
for x in range(3): | |
next(m) |
三. 协程
协程不是过程,也不是线程,它是用户空间调度的实现的并发解决的形式。
它是 python 中另外一种实现多任务的形式,只不过比线程更小,占用更小执行单元。为啥说它是一个执行单元,因为它自带 CPU 上下文。这样只有在适合的机会,咱们能够把一个协程 切换到另一个协程。只有这个过程中保留或复原 CPU 上下文那么程序还是能够运行的。
协程是线程内实现调度, 它不须要更多的线程,天然也没有多线程切换带来的开销。
协程是非抢占式调度,只有一个协程被动让出控制权,另一个协程才会被调度。
协程也不须要应用锁机制,因为是在同一个线程中执行。
- 简略实现一个协程
def a(): | |
for x in range(3): | |
print(x) | |
yield | |
def b(): | |
for x in range(3): | |
print(x) | |
yield | |
m = a() | |
n = b() | |
for x in range(3): | |
next(m) | |
next(n) |
在线程内通过生成器实现了调度,让两个函数简直都有执行,这样的调度不是操作系统的过程、线程实现的,而是用户本人设计的,这个就是协程。
- greenlet 实现协程
from greenlet import greenlet | |
import time | |
def test1(): | |
while True: | |
print("---test1---") | |
g2.switch() | |
time.sleep(0.5) | |
def test2(): | |
while True: | |
print("---test2---") | |
g1.switch() | |
time.sleep(0.5) | |
g1 = greenlet(test1) | |
g2 = greenlet(test2) | |
#切换到 g1 中运行 | |
g1.switch() |
- gevent 比 greenlet 更加弱小,可能主动切换
示例 1
import gevent | |
def fun(n): | |
for x in range(n): | |
print(gevent.getcurrent(), x) | |
gevent.sleep(1) | |
g1 = gevent.spawn(fun, 5) # 第一个参数为传递的执行函数,第二个参数,是 f 的参数 | |
g2 = gevent.spawn(fun, 5) | |
g3 = gevent.spawn(fun, 5) | |
g1.join() | |
g2.join() | |
g3.join() |
示例 2
from gevent import monkey | |
import gevent | |
import random | |
import time | |
monkey.patch_all() | |
def coroutine_work(coroutine_name): | |
for i in range(10): | |
print(coroutine_name, i) | |
time.sleep(random.random()) | |
gevent.joinall([gevent.spawn(coroutine_work, "work1"), | |
gevent.spawn(coroutine_work, "work2") | |
]) |
示例 3
from gevent import monkey | |
import gevent | |
import random | |
import time | |
from gevent.pool import Pool | |
pool = Pool(5) # 限度发送协程数 | |
monkey.patch_all() | |
# | |
def coroutine_work(coroutine_name): | |
for i in range(10): | |
print(coroutine_name, i) | |
time.sleep(random.random()) | |
gevent.joinall([pool.spawn(coroutine_work, coroutine_name='work1'), | |
pool.spawn(coroutine_work, coroutine_name='work2'), | |
] | |
) |