博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Python中的生成器与yield
阅读量:4472 次
发布时间:2019-06-08

本文共 3039 字,大约阅读时间需要 10 分钟。

对于python中的yield有些疑惑,然后在StackOverflow上看到了,所以搬运过来了,英文好的直接看原文吧。

可迭代对象

当你创建一个列表的时候,你可以一个接一个地读取其中的项。一个接一个地读项就叫做迭代

>>> mylist = [1, 2, 3]>>> for i in mylist:... print(i)123

mylist就是一个可迭代对象。你使用列表推导式时,就创建了一个列表,也就是一个可迭代对象:

>>> mylist = [x*x for x in range(3)]>>> for i in mylist:... print(i)014

任何可以用“for...in...”操作的事物都是可迭代对象;列表,字符串,文件……

这些可迭代对象很方便,因为你可以随意地访问它们,但是你把所有的值都保存在内存中。如果你有大量的数据的话,这就不是你想要的了。

生成器

生成器是迭代器,但是你只可以对它们进行一次迭代。这是因为你没有在内存中存储所有数值,它们动态地生成值

>>> mygenerator = (x*x for x in range(3))>>> for i in mygenerator:... print(i)014

跟上面的例子基本一样,除了用()代替了[]。但是,你不能第二次执行for i in mygenerator,因为生成器只能使用一次;它计算出0,然后忘掉0并计算1,最后是计算4,一个接一个地进行。

Yield

Yield是一个像return一样的关键字,只不过函数返回的是一个生成器:

>>> def createGenerator():... mylist = range(3)... for i in mylist:... yield i*i...>>> mygenerator = createGenerator() # 创建一个迭代器>>> print(mygenerator) # mygenerator是一个对象!
>>> for i in mygenerator:... print(i)014>>> for i in mygenerator:print(i)>>>

这个例子里的生成器没什么用,但是如果你知道你的函数会返回大量的数据,而你只需要对这些数据读取一次时,那就变得很有用了。

要掌握yield你必须理解当你访问函数的时候,你写在函数体中的代码并没有执行。这个函数只是返回了迭代器对象,这一点很微妙。

然后,每次for语句使用生成器的时候,你的代码就会运行。

然后是最难的部分:

for语句第一次调用从你的函数中创建的迭代器对象时,它就会运行你函数中的代码,从开始一直到它碰见yield,然后它就返回这个循环中的第一个值。之后,每一次的调用都会再一次运行你写在函数里的循环,然后返回下一个值,直到没有值可以被返回。

一旦函数运行但是没有再碰到yield,生成器就被认为是空的。这可能是因为循环已经结束了,或者因为不再满足if/else条件了。

控制生成器耗尽

>>> class Bank(): # let's create a bank, building ATMs... crisis = False... def create_atm(self):... while not self.crisis:... yield "$100">>> hsbc = Bank() # when everything's ok the ATM gives you as much as you want>>> corner_street_atm = hsbc.create_atm()>>> print(corner_street_atm.next())$100>>> print(corner_street_atm.next())$100>>> print([corner_street_atm.next() for cash in range(5)])['$100', '$100', '$100', '$100', '$100']>>> hsbc.crisis = True # crisis is coming, no more money!>>> print(corner_street_atm.next())
>>> wall_street_atm = hsbc.create_atm() # it's even true for new ATMs>>> print(wall_street_atm.next())
>>> hsbc.crisis = False # trouble is, even post-crisis the ATM remains empty>>> print(corner_street_atm.next())
>>> brand_new_atm = hsbc.create_atm() # build a new one to get back in business>>> for cash in brand_new_atm:... print cash$100$100$100$100$100$100$100$100$100...

这个在很多方面都有用,比如控制对某个资源的访问。

Itertools,好帮手

itertools模块包含操作可迭代对象的特殊函数。想要复制一个生成器?连接两个生成器?把嵌套列表中的数据整理到一个列表中?不创建另一个列表就直接Map/Zip?

那就import itertools

例子?那我们看看4马比赛中所有可能的到达顺序(全排列):

>>> horses = [1, 2, 3, 4]>>> races = itertools.permutations(horses)>>> print(races)
>>> print(list(itertools.permutations(horses)))[(1, 2, 3, 4),(1, 2, 4, 3),(1, 3, 2, 4),(1, 3, 4, 2),(1, 4, 2, 3),(1, 4, 3, 2),(2, 1, 3, 4),(2, 1, 4, 3),(2, 3, 1, 4),(2, 3, 4, 1),(2, 4, 1, 3),(2, 4, 3, 1),(3, 1, 2, 4),(3, 1, 4, 2),(3, 2, 1, 4),(3, 2, 4, 1),(3, 4, 1, 2),(3, 4, 2, 1),(4, 1, 2, 3),(4, 1, 3, 2),(4, 2, 1, 3),(4, 2, 3, 1),(4, 3, 1, 2),(4, 3, 2, 1)]

理解迭代的内部机制

迭代是一个暗含可迭代对象(实现了__iter__()方法)和迭代器(实现了__next__()方法)的过程。可迭代对象是任何你可以从中得到迭代器的对象。迭代器是可以让你对可迭代对象进行迭代的对象。

更多信息请参考。

转载于:https://www.cnblogs.com/GuoYaxiang/p/6215685.html

你可能感兴趣的文章
linux 小技巧(磁盘空间搜索)
查看>>
iOS开发——捕获崩溃信息
查看>>
(for 循环)编程找出四位整数 abcd 中满足 (ab+cd)(ab+cd)=abcd 的数
查看>>
tomcat使用spring-loaded实现应用热部署
查看>>
boost1.53中的lock-free
查看>>
链表_leetcode203
查看>>
基于ajax 的 几个例子 session ,ajax 实现登录,验证码 ,实现ajax表单展示
查看>>
连接不上sql server服务器的解决方案
查看>>
c3po数据库连接池中取出连接
查看>>
使用本机IP调试web项目
查看>>
【Java面试题】58 char型变量中能不能存贮一个中文汉字?为什么?
查看>>
C++ Primer 第六章 函数
查看>>
交互设计算法基础(3) - Quick Sort
查看>>
Ubuntu各种软件的安装
查看>>
java开发环境搭建-慕课网
查看>>
NOIP2015-D2T3运输计划
查看>>
Z :彻底了解指针数组,数组指针以及函数指针 [复
查看>>
2013年终总结
查看>>
Start to study Introduction to Algorithms
查看>>
AE常见接口之间的关系(较笼统)+arcgis常见概念
查看>>