视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
python生成器generator介绍
2020-11-27 14:23:29 责编:小采
文档


  在跟着廖雪峰的博客学习python,看到生成器这一章节的时候,首先提到了generator 、yield,然后在搜索资料的时候,又查到了协程这一概念,这篇文章总结一下这几个概念.

  generator 从字面上理解,就是生成器,它的实现方式有两种:

1、不同于列表生成器([]),而是用 ()来表示。(原来这种叫做生成器表达式哦,哈哈)

访问方式,可以用for 循环来访问,也可以用 .next 来访问。

N = ['Hello', 'World', 18, 'Apple', 'None']
hh = (s.lower() for s in N if isinstance(s,str) ==True)print hh#for item in hh:# print item#print hh.next()#print hh.next()#print hh.next()#print hh.next()

输出结果

<generator object <genexpr> at 0x7f543a074690>
hello
world
apple
none

hh 是生成器返回的值,类似于一个数组。支持 for循环访问和 .next()访问,有一点需要注意的是,for 循环执行完了之后就不能执行 hh.next()了,类似于指针到了最后,或者C++中迭代器指向了最后,再访问就会出现错误。

2、用yield来生成 ,(叫做生成器函数)

无论用next() 和for 循环来调用,都是执行到了yield之后,返回 n值,然后将当前的状态挂起,然后返回。

def create_counter(n):print "create counter"#while True:while False:yield nprint 'increment n'n += 1cnt = create_counter(2)#print cntfor item in cnt:print item#print next(cnt)#print next(cnt)#print cnt.next()#print cnt.next()

比如这个例子中,当打印cnt的时候,<generator object create_counter at 0x7fa992b8d6e0>

说明这是一个,生成器。
当 为False的时候,只会打印 create counter

当为True的时候,用for 循环就会出现死循环的情况。

协程:

我知道有进程、线程的概念,但是协程是什么东西,我还真是不知道

从技术的角度来说,“协程就是你可以暂停执行的函数”。如果你把它理解成“就像生成器一样”,那么你就想对了。这是在一篇文章上看到的。

python之所以执行效率高

1、为子程序切换不是线程切换,而是由程序自身控制,因此,没有线程切换的开销,和多线程比,线程数量越多,协程的性能优势就越明显。

2、执行的过程中不会涉及到锁机制。

附一个简单的生产者和消费者的例子:

def consumer():
 r = ''while True:
 n = yield rif not n:returnprint('[CONSUMER] Consuming %s...' % n)
 time.sleep(1)
 r = '200 OK'def produce(c):
 c.next()
 n = 0while n < 5:
 n = n + 1print('[PRODUCER] Producing %s...' % n)
 r = c.send(n)print('[PRODUCER] Consumer return: %s' % r)
 c.close()if __name__=='__main__':
 c = consumer()
 produce(c)

1. consumer函数是一个generator。
2. c.send(None)其实等价于next(c),第一次执行时其实只执行到n = yield r就停止了,然后把r的值返回给调用者。
3. yield r是一个表达式,通过send(msg)被赋值,而send(msg)是有返回值的,返回值为:下一个yield r表达式的参数,即为r。
4. produce一旦生产了东西,通过c.send(n)切换到consumer执行。consumer通过yield拿到消息,处理,又通过yield把结果传回。也就是说,c.send(1) 不但会给 c 传送一个数据,它还会等着下次 yield 从 c 中返回一个数据,它是有返回值的,一去一回才算完,拿到了返回的数据(200 OK)才继续下面执行。
5. 整个流程无锁,由一个线程执行,produce和consumer协作完成任务,所以称为“协程”,而非线程的抢占式多任务。

总结来说,就是 yield r 是一个表达式,通过 c.send 被赋值,然后返回值为下一个为yield r 表达式的参数。

下载本文
显示全文
专题