1. 首页
  2. Python

看完这篇文章,你就不会在为迭代器和生成器而感到苦恼

“u003Cdivu003Eu003Cpu003E1、迭代器和迭代过程u003Cu002Fpu003Eu003Cpu003E维基百科解释道:u003Cu002Fpu003Eu003Cblockquoteu003Eu003Cpu003E在Python中,迭代器是遵循迭代协议的对象。使用iter()从任何序列对象中得到迭代器(如list, tuple, dictionary, set等)。另一种形式的输入迭代器是generator(生成器)。u003Cu002Fpu003Eu003Cu002Fblockquoteu003Eu003Cpu003E很多容器诸如列表、字符串可以用for循环遍历对象。for 语句会调用容器对象中的 iter()函数, 该函数返回一个定义了 __next__() 方法的迭代器对象,该方法将逐一访问容器中的元素。u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp1.pstatp.comu002Flargeu002Fdfic-imagehandleru002F147924fa-f940-410c-98f0-f4bb74a09fed” img_width=”1024″ img_height=”1024″ alt=”看完这篇文章,你就不会在为迭代器和生成器而感到苦恼” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E所以说:python中,任意对象,只要定义了__next__方法,它就是一个迭代器。因此,python中的容器如列表、元组、字典、集合、字符串都可以被称作迭代器。u003Cu002Fpu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp3.pstatp.comu002Flargeu002Fpgc-imageu002F00591064f69c4b26afa70b8015bb33a1″ img_width=”696″ img_height=”360″ alt=”看完这篇文章,你就不会在为迭代器和生成器而感到苦恼” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpu003E讲完迭代器后,迭代就比较好理解了,迭代就是从迭代器中取元素的过程。u003Cu002Fpu003Eu003Cpu003E比如我们用u003Cemu003Eforu003Cu002Femu003E循环从列表[1,2,3]中取元素,这种遍历过程就被称作迭代。u003Cu002Fpu003Eu003Cpreu003E# 列表是迭代器u003Cbru003Efor element in [1, 2, 3]:u003Cbru003E print(element)u003Cbru003E# 元组是迭代器u003Cbru003Efor element in (1, 2, 3):u003Cbru003E print(element)u003Cbru003E# 字典是迭代器u003Cbru003Efor key in {‘one’:1, ‘two’:2}:u003Cbru003E print(key)u003Cbru003E# 字符串是迭代器u003Cbru003Efor char in “123”:u003Cbru003E print(char)u003Cbru003E# 打开的text同样是迭代器u003Cbru003Efor line in open(“myfile.txt”):u003Cbru003E print(line, end=”)u003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E如果你不想用for循环迭代呢?这时你可以:u003Cu002Fpu003Eu003Colu003Eu003Cliu003E先调用容器(以字符串为例)的iter()函数再使用 u003Cemu003Enext()u003Cu002Femu003E 内置函数来调用 u003Cemu003E__next__()u003Cu002Femu003E 方法当元素用尽时,u003Cemu003E__next__() u003Cu002Femu003E将引发 StopIteration 异常u003Cu002Fliu003Eu003Cu002Folu003Eu003Cdiv class=”pgc-img”u003Eu003Cimg src=”http:u002Fu002Fp9.pstatp.comu002Flargeu002Fpgc-imageu002Fb04f864a233d41dd902f6b40a5fb975b” img_width=”720″ img_height=”267″ alt=”看完这篇文章,你就不会在为迭代器和生成器而感到苦恼” inline=”0″u003Eu003Cp class=”pgc-img-caption”u003Eu003Cu002Fpu003Eu003Cu002Fdivu003Eu003Cpreu003E>>> s = ‘abc’ u003Cbru003E>>> it = iter(s)u003Cbru003E>>> itu003Cbru003E<iterator object at 0x00A1DB50>u003Cbru003E>>> next(it)u003Cbru003E’a’u003Cbru003E>>> next(it)u003Cbru003E’b’u003Cbru003E>>> next(it)u003Cbru003E’c’u003Cbru003E>>> next(it)u003Cbru003ETraceback (most recent call last):u003Cbru003E File “<stdin>”, line 1, in <module>u003Cbru003E next(it)u003Cbru003EStopIterationu003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E2、生成器 Generatorsu003Cu002Fpu003Eu003Cpu003E看看廖雪峰大神的解释:u003Cu002Fpu003Eu003Cblockquoteu003Eu003Cpu003E通过列表生成式,我们可以直接创建一个列表。u003Cu002Fpu003Eu003Cpu003E但是,受到内存限制,列表容量肯定是有限的。u003Cu002Fpu003Eu003Cpu003E而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。u003Cu002Fpu003Eu003Cpu003E所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?u003Cu002Fpu003Eu003Cpu003E这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器(Generator)。u003Cu002Fpu003Eu003Cu002Fblockquoteu003Eu003Cpu003E生成器也是一种迭代器,但是你只能对其迭代一次。这是因为它们并没有把所有的值存在内存中,而是在运行时生成值。u003Cu002Fpu003Eu003Cpu003E你通过遍历来使用它们,要么用一个u003Cemu003Eforu003Cu002Femu003E循环,要么将它们传递给任意可以进行迭代的函数和结构。大多数时候生成器是以函数来实现的。然而,它们并不返回一个值,而是u003Cemu003Eyieldu003Cu002Femu003E(暂且译作“生出”)一个值。u003Cu002Fpu003Eu003Cpu003E每次对生成器调用 u003Cemu003Enext()u003Cu002Femu003E 时,它会从上次离开位置恢复执行(它会记住上次执行语句时的所有数据值)。显示如何非常容易地创建生成器的示例如下:u003Cu002Fpu003Eu003Cpreu003Edef reverse(data):u003Cbru003E for index in range(len(data)-1, -1, -1):u003Cbru003E yield data[index]u003Cbru003E>>> for char in reverse(‘golf’):u003Cbru003E… print(char)u003Cbru003E…u003Cbru003Efu003Cbru003Elu003Cbru003Eou003Cbru003Egu003Cbru003Eu003Cu002Fpreu003Eu003Cpu003E可以用生成器来完成的操作同样可以用前一节所描述的基于类的迭代器来完成。但生成器的写法更为紧凑,因为它会自动建 u003Cemu003E__iter__()u003Cu002Femu003E 和 u003Cemu003E__next__()u003Cu002Femu003E方法。u003Cu002Fpu003Eu003Cpu003E3、生成器表达式u003Cu002Fpu003Eu003Cpu003E生成器不一定要用复杂的函数表示,python提供了简洁的生成器表达式。u003Cu002Fpu003Eu003Cpu003E从形式上来看,生成器表达式和列表推导式很像,仅仅是将列表推导式中的[]替换为(),但是两者差别挺大,生成器表达式可以说组合了迭代功能和列表解析功能。u003Cu002Fpu003Eu003Cpu003E生成器表达式可以认为是一种特殊的生成器函数,类似于lambda表达式和普通函数。但是和生成器一样,生成器表达式也是返回生成器generator对象,一次只返回一个值。u003Cu002Fpu003Eu003Cpreu003E>>> sum(i*i for i in range(10)) # sum of squaresu003Cbru003E285u003Cbru003E>>> xvec = [10, 20, 30]u003Cbru003E>>> yvec = [7, 5, 3]u003Cbru003E>>> sum(x*y for x,y in zip(xvec, yvec)) # dot productu003Cbru003E260u003Cbru003E>>> from math import pi, sinu003Cbru003E>>> sine_table = {x: sin(x*piu002F180) for x in range(0, 91)}u003Cbru003E>>> unique_words = set(word for line in page for word in line.split())u003Cbru003E>>> valedictorian = max((student.gpa, student.name) for student in graduates)u003Cbru003E>>> data = ‘golf’u003Cbru003E>>> list(data[i] for i in range(len(data)-1, -1, -1))u003Cbru003E[‘f’, ‘l’, ‘o’, ‘g’]u003Cbru003E最后多说一句,小编是一名python开发工程师,这里有我自己整理了一套最新的python系统学习教程,包括从基础的python脚本到web开发、爬虫、数据分析、数据可视化、机器学习等。想要这些资料的可以关注小编,并在后台私信小编:“01”即可领取。u003Cbru003Eu003Cu002Fpreu003Eu003Cu002Fdivu003E”

原文始发于:看完这篇文章,你就不会在为迭代器和生成器而感到苦恼

主题测试文章,只做测试使用。发布者:逗乐男神i,转转请注明出处:http://www.cxybcw.com/12898.html

联系我们

13687733322

在线咨询:点击这里给我发消息

邮件:1877088071@qq.com

工作时间:周一至周五,9:30-18:30,节假日休息

QR code