Python Generator函数和协程

Python Generator函数和协程

学习Generator函数之前要了解一些定义

迭代器(Iterator)

对象定义了__next__ 方法就是迭代器。

可迭代对象(Iterable)

对象可以定义__iter__用来返回迭代器的方法,或者定义__getitem__ 通过下标获取元素的方法,含有这两种方法的对象就是可迭代的。

生成器(Generator)

返回值用yield返回的函数,生成器是创建迭代器的最简单方式,自动实现__iter____next__方法

def generatorFunc():
        for i in range(0, 10):
                yield i  #这句需要注意,生成器函数专用

for v in generatorFunc():
        print(v)
''' 结果: 0 1 2 3 4 5 6 7 8 9 '''

yield 类似普通函数的return,每次执行到yield则返回一次其后的值然后暂停执行,并不是一次生成所有值后返回,而是在执行next时继续执行到下一次的yield。这样做的好处是返回的是非常多的数据时并不是一次全部生成,而是按次序生成,这样可以节省很多空间。

for a in fibo(10):
def fibo(n):
        x1=x2=1
        for i in range(n):
                yield x1
                x1,x2 = x2, x1+x2

gen = fibo(3) #获取迭代器对象

print(next(gen)) #使用next获取写一个yield后的值
print(next(gen))
print(next(gen))
print(next(gen))#报错StopIteration,使用next方法如果没有yield再生成值返回则会报错, next是迭代器返回值使用的函数
''' 结果: 1 1 2 Traceback (most recent call last): File "fibo.py", line 12, in <module> print(next(gen)) StopIteration '''

注意可迭代和迭代器的区别,如:string是可以通过下标访问的,所以string是iterable 但是他却不是迭代器
但是可迭代对象是可以通过内建函数iter转换成迭代器

>>> a = '1234'
>>> next(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: 'str' object is not an iterator
>>> i = iter(a) #通过iter把可迭代对象转换成迭代器
>>> next(i)
'1'

Python3中很多函数再返回多个值时返回的是迭代器,如map 、filter等

协程

协程又叫做微线程,和线程不一样,协程是在一个线程执行,但是比线程运行效率高,它不需要线程切换的开销,也不需要锁机制来控制同步互斥,它与函数调用很相似,但是和函数调用又很大区别,并不是使用函数栈来控制。
协程需要使用生成器方式来实现,之前我们使用生成器来生产数据,携程用法相反,我们生产数据,发送给协程来消费。
先看例子:

def grep(p): 
        print(p)
        x = 0;
        while True:
                x+=1
                line = (yield x)
                print(line)

g = grep('grep') #返回一个生成器对象

r = next(g) #启动生成器 或者使用g.send(None)来启动

print(r)   #返回yield之后的x 并使携程暂停在yield位置

r = g.send('aaa') #通过使用send向协程传递‘aaa’使yield语句返回‘aaa’,并返回yield后的值
print(r)

g.close()#关闭携程
''' 结果: grep 1 aaa 2 '''
  1. 首先我们需要调用next或者send(None)来启动生成器。
  2. 我们发送数据到协程使用x = send(value)把value发送到协程,然后接受yield的数据,协程接着运行到yield,然后我们再用send发送数据和接收值…
  3. 关闭协程使用close函数关闭

你可能感兴趣的:(python)