python迭代器生成器
Ⅰ python迭代器和生成器区别是什么
python中迭代器和生成器的区别
1、共同点
生成器是一种特殊的迭代器。
相关推荐:《Python视频教程》
2、不同点
a、语法上:
生成器是通过函数的形式中调用 yield 或()的形式创建的。
迭代器可以通过 iter() 内置函数创建。
b、用法上:
生成器在调用next()函数或for循环中,所有过程被执行,且返回值。
迭代器在调用next()函数或for循环中,所有值被返回,没有其他过程或动作。
Ⅱ Python中迭代器和生成器的区别与联系
用代码说明下
defmiter():
returnlist(range(10))
defmyield():
foriinrange(10):
yieldi
print(miter())
print(myield())
输出是
[0,1,2,3,4,5,6,7,8,9]
<>
不知道,你发现什么东西没?
迭代器,是直接返回我们要的数据,
那么假设,我现在要一亿条,是的。迭代器会一次性给你1亿条。
这个对内存是由比较大的消耗的。
那如果我们使用,生成器,你会发现
没有什么压力的,多少都可以给你。
因为,生成器的原理,就只是 记录当前数据的位置,
然后你需要的时候给你返回下一条
这个也是为什么大家都喜欢用 生成器的原因。
Ⅲ Python中生成器和迭代器的区别
先说迭代器,对于string、list、dict、tuple等这类容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()函数,iter()是python的内置函数。iter()会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内元素,next()也是python的内置函数。在没有后续元素时,next()会抛出一个StopIteration异常,通知for语句循环结束。
生成器(Generator)是创建迭代器的简单而强大的工具。它们写起来就像是正规的函数,只是在需要返回数据的时候使用yield语句。每次next()被调用时,生成器会返回它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)。
Ⅳ Python中生成器和迭代器的区别详解
Num01–>迭代器
定义:
对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()函数。iter()是python内置函数。
iter()函数会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内的元素。next()也是python内置函数。在没有后续元素时,next()会抛出一个StopIteration异常,通知for语句循环结束。
迭代器是用来帮助我们记录每次迭代访问到的位置,当我们对迭代器使用next()函数的时候,迭代器会向我们返回它所记录位置的下一个位置的数据。实际上,在使用next()函数的时候,调用的就是迭代器对象的_next_方法(Python3中是对象的_next_方法,Python2中是对象的next()方法)。所以,我们要想构造一个迭代器,就要实现它的_next_方法。但这还不够,python要求迭代器本身也是可迭代的,所以我们还要为迭代器实现_iter_方法,而_iter_方法要返回一个迭代器,迭代器自身正是一个迭代器,所以迭代器的_iter_方法返回自身self即可。
Num02–>生成器
作用:
>延迟操作。也就是在需要的时候才产生结果,不是立即产生结果。12
注意事项:
>生成器是只能遍历一次的。
>生成器是一类特殊的迭代器。
Ⅳ python 生成器和迭代器的区别
1、迭代器(iterator)是一个实现了迭代器协议的对象,python的一些内置数据类型(列表,数组,字符串,字典等)都可以通过for语句进行迭代,我们也可以自己创建一个容器,实现了迭代器协议,可以通过for,next方法进行迭代,在迭代的末尾,会引发stopIteration异常。
2、生成器(generator)是通过yield语句快速生成迭代器,可以不用iter和next方法
yield可以使一个普通函数变成一个生成器,并且相应的next()方法返回是yield后的值。一种更直观的解释是:程序执行到yield时会返回结果并暂停,再次调用next时会从上次暂停的地方继续开始执行。
显然,生成器自身有构成一个迭代器,每次迭代时使用一个yield返回 的值,一个生成器中可以有多个yield的值
Ⅵ 如何更好地理解Python迭代器和生成器
在Python这门语言中,生成器毫无疑问是最有用的特性之一。与此同时,也是使用的最不广泛的Python特性之一。究其原因,主要是因为,在其他主流语言里面没有生成器的概念。正是由于生成器是一个“新”的东西,所以,它一方面没有引起广大工程师的重视,另一方面,也增加了工程师的学习成本,最终导致大家错过了Python中如此有用的一个特性。
我的这篇文章,希望通过简单易懂的方式,深入浅出地介绍Python的生成器,以改变“如此有用的特性却使用极不广泛”的现象。本文的组织如下:在第1章,我们简单地介绍了Python中的迭代器协议;在本文第2章,将会详细介绍生成器的概念和语法;在第3章,将会给出一个有用的例子,说明使用生成器的好处;在本文最后,简单的讨论了使用生成器的注意事项。
1. 迭代器协议
由于生成器自动实现了迭代器协议,而迭代器协议对很多人来说,也是一个较为抽象的概念。所以,为了更好的理解生成器,我们需要简单的回顾一下迭代器协议的概念。
迭代器协议是指:对象需要提供next方法,它要么返回迭代中的下一项,要么就引起一个StopIteration异常,以终止迭代
可迭代对象就是:实现了迭代器协议的对象
协议是一种约定,可迭代对象实现迭代器协议,Python的内置工具(如for循环,sum,min,max函数等)使用迭代器协议访问对象。
举个例子:在所有语言中,我们都可以使用for循环来遍历数组,Python的list底层实现是一个数组,所以,我们可以使用for循环来遍历list。如下所示:
>>> for n in [1, 2, 3, 4]:
... print n
但是,对Python稍微熟悉一点的朋友应该知道,Python的for循环不但可以用来遍历list,还可以用来遍历文件对象,如下所示:
>>> with open(‘/etc/passwd’) as f: # 文件对象提供迭代器协议
... for line in f: # for循环使用迭代器协议访问文件
... print line
...
为什么在Python中,文件还可以使用for循环进行遍历呢?这是因为,在Python中,文件对象实现了迭代器协议,for循环并不知道它遍历的是一个文件对象,它只管使用迭代器协议访问对象即可。正是由于Python的文件对象实现了迭代器协议,我们才得以使用如此方便的方式访问文件,如下所示:
>>> f = open('/etc/passwd')
>>> dir(f)
['__class__', '__enter__', '__exit__', '__iter__', '__new__', 'writelines', '...'
2. 生成器
Python使用生成器对延迟操作提供了支持。所谓延迟操作,是指在需要的时候才产生结果,而不是立即产生结果。这也是生成器的主要好处。
Python有两种不同的方式提供生成器:
生成器函数:常规函数定义,但是,使用yield语句而不是return语句返回结果。yield语句一次返回一个结果,在每个结果中间,挂起函数的状态,以便下次重它离开的地方继续执行
生成器表达式:类似于列表推导,但是,生成器返回按需产生结果的一个对象,而不是一次构建一个结果列表
2.1 生成器函数
我们来看一个例子,使用生成器返回自然数的平方(注意返回的是多个值):
def gensquares(N):
for i in range(N):
yield i ** 2
for item in gensquares(5):
print item,
使用普通函数:
def gensquares(N):
res = []
for i in range(N):
res.append(i*i)
return res
for item in gensquares(5):
print item,
可以看到,使用生成器函数代码量更少。
2.2 生成器表达式
使用列表推导,将会一次产生所有结果:
>>> squares = [x**2 for x in range(5)]
>>> squares
[0, 1, 4, 9, 16]
将列表推导的中括号,替换成圆括号,就是一个生成器表达式:
>>> squares = (x**2 for x in range(5))
>>> squares
<generator object at 0x00B2EC88>
>>> next(squares)
0
>>> next(squares)
1
>>> next(squares)
4
>>> list(squares)
[9, 16]
Python不但使用迭代器协议,让for循环变得更加通用。大部分内置函数,也是使用迭代器协议访问对象的。例如, sum函数是Python的内置函数,该函数使用迭代器协议访问对象,而生成器实现了迭代器协议,所以,我们可以直接这样计算一系列值的和:
>>> sum(x ** 2 for x in xrange(4))
而不用多此一举的先构造一个列表:
>>> sum([x ** 2 for x in xrange(4)])
2.3 再看生成器
前面已经对生成器有了感性的认识,我们以生成器函数为例,再来深入探讨一下Python的生成器:
语法上和函数类似:生成器函数和常规函数几乎是一样的。它们都是使用def语句进行定义,差别在于,生成器使用yield语句返回一个值,而常规函数使用return语句返回一个值
自动实现迭代器协议:对于生成器,Python会自动实现迭代器协议,以便应用到迭代背景中(如for循环,sum函数)。由于生成器自动实现了迭代器协议,所以,我们可以调用它的next方法,并且,在没有值可以返回的时候,生成器自动产生StopIteration异常
状态挂起:生成器使用yield语句返回一个值。yield语句挂起该生成器函数的状态,保留足够的信息,以便之后从它离开的地方继续执行
3. 示例
我们再来看两个生成器的例子,以便大家更好的理解生成器的作用。
首先,生成器的好处是延迟计算,一次返回一个结果。也就是说,它不会一次生成所有的结果,这对于大数据量处理,将会非常有用。
大家可以在自己电脑上试试下面两个表达式,并且观察内存占用情况。对于前一个表达式,我在自己的电脑上进行测试,还没有看到最终结果电脑就已经卡死,对于后一个表达式,几乎没有什么内存占用。
sum([i for i in xrange(10000000000)])
sum(i for i in xrange(10000000000))
除了延迟计算,生成器还能有效提高代码可读性。例如,现在有一个需求,求一段文字中,每个单词出现的位置。
不使用生成器的情况:
def index_words(text):
result = []
if text:
result.append(0)
for index, letter in enumerate(text, 1):
if letter == ' ':
result.append(index)
return result
使用生成器的情况:
def index_words(text):
if text:
yield 0
for index, letter in enumerate(text, 1):
if letter == ' ':
yield index
这里,至少有两个充分的理由说明 ,使用生成器比不使用生成器代码更加清晰:
使用生成器以后,代码行数更少。大家要记住,如果想把代码写的Pythonic,在保证代码可读性的前提下,代码行数越少越好
不使用生成器的时候,对于每次结果,我们首先看到的是result.append(index),其次,才是index。也就是说,我们每次看到的是一个列表的append操作,只是append的是我们想要的结果。使用生成器的时候,直接yield index,少了列表append操作的干扰,我们一眼就能够看出,代码是要返回index。
这个例子充分说明了,合理使用生成器,能够有效提高代码可读性。只要大家完全接受了生成器的概念,理解了yield语句和return语句一样,也是返回一个值。那么,就能够理解为什么使用生成器比不使用生成器要好,能够理解使用生成器真的可以让代码变得清晰易懂。
4. 使用生成器的注意事项
相信通过这篇文章,大家已经能够理解生成器的作用和好处。但是,还没有结束,使用生成器,也有一点注意事项。
我们直接来看例子,假设文件中保存了每个省份的人口总数,现在,需要求每个省份的人口占全国总人口的比例。显然,我们需要先求出全国的总人口,然后在遍历每个省份的人口,用每个省的人口数除以总人口数,就得到了每个省份的人口占全国人口的比例。
如下所示:
def get_province_population(filename):
with open(filename) as f:
for line in f:
yield int(line)
gen = get_province_population('data.txt')
all_population = sum(gen)
#print all_population
for population in gen:
print population / all_population
执行上面这段代码,将不会有任何输出,这是因为,生成器只能遍历一次。在我们执行sum语句的时候,就遍历了我们的生成器,当我们再次遍历我们的生成器的时候,将不会有任何记录。所以,上面的代码不会有任何输出。
因此,生成器的唯一注意事项就是:生成器只能遍历一次。
5. 总结
本文深入浅出地介绍了Python中,一个容易被大家忽略的重要特性,即Python的生成器。为了讲解生成器,本文先介绍了迭代器协议,然后介绍了生成器函数和生成器表达式,并通过示例演示了生成器的优点和注意事项。在实际工作中,充分利用Python生成器,不但能够减少内存使用,还能够提高代码可读性。掌握生成器也是Python高手的标配。希望本文能够帮助大家理解Python的生成器。
Ⅶ python中迭代器和生成器的区别
对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的。在后台for语句对容器对象调用iter()函数。iter()是Python内置函数。
iter()会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内的元素。next()也是python内置函数。在没有后续元素时,next()会抛出一个StopIteration异常,通知for语句循环结束。
Ⅷ python生成器和迭代器的区别
迭代器和生成器都是Python中特有的概念,迭代器可以看作是一个特殊的对象,每次调用该对象时会返回自身的下一个元素,从实现上来看,一个可迭代的对象必须是定义了__iter__()方法的对象,而一个迭代器必须是定义了__iter__()方法和next()方法的对象。生成器的概念要比迭代器稍显复杂,因为生成器是能够返回一个迭代器的函数,其最大的作用是将输入对象返回为一个迭代器。Python中使用了迭代的概念,是因为当需要循环遍历一个较大的对象时,传统的内存载入方式会消耗大量的内存,不如需要时读取一个元素的方式更为经济快捷。
迭代器
迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机的统一起来。
迭代器提供一些基本操作符:*、++、==、!=、=。这些操作和C/C++“操作array元素”时的指针接口一致。不同之处在于,迭代器是个所谓的复杂的指针,具有遍历复杂数据结构的能力。其下层运行机制取决于其所遍历的数据结构。因此,每一种容器型别都必须提供自己的迭代器。事实上每一种容器都将其迭代器以嵌套的方式定义于内部。因此各种迭代器的接口相同,型号却不同。这直接导出了泛型程序设计的概念:所有操作行为都使用相同接口,虽然它们的型别不同。
迭代器使开发人员能够在类或结构中支持foreach迭代,而不必整个实现IEnumerable或者IEnumerator接口。只需提供一个迭代器,即可遍历类中的数据结构。当编译器检测到迭代器时,将自动生成IEnumerable接口或者IEnumerator接口的Current,MoveNext和Dispose方法。
生成器
生成器是一次生成一个值的特殊类型函数。可以将其视为可恢复函数。调用该函数将返回一个可用于生成连续 x 值的生成器【Generator】
简单的说就是在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。
Ⅸ Python中生成器的理解
9.10. 生成器
Generator 是创建迭代器的简单而强大的工具。它们写起来就像是正规的函数,需要返回数据的时候使用 yield 语句。每次 next() 被调用时,生成器回复它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)。以下示例演示了生成器可以很简单的创建出来:
前一节中描述了基于类的迭代器,它能作的每一件事生成器也能作到。因为自动创建了 __iter__() 和 __next__() 方法,生成器显得如此简洁。
另一个关键的功能在于两次执行之间,局部变量和执行状态都自动的保存下来。这使函数很容易写,而且比使用 self.index 和 self.data 之类的方式更清晰。
除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出 StopIteration 异常。综上所述,这些功能使得编写一个正规函数成为创建迭代器的最简单方法。
Generator 是创建迭代器的简单而强大的工具。它们写起来就像是正规的函数,需要返回数据的时候使用 yield 语句。每次 next() 被调用时,生成器回复它脱离的位置(它记忆语句最后一次执行的位置和所有的数据值)。以下示例演示了生成器可以很简单的创建出来:
前一节中描述了基于类的迭代器,它能作的每一件事生成器也能作到。因为自动创建了 __iter__() 和 __next__() 方法,生成器显得如此简洁。
另一个关键的功能在于两次执行之间,局部变量和执行状态都自动的保存下来。这使函数很容易写,而且比使用 self.index 和 self.data 之类的方式更清晰。
除了创建和保存程序状态的自动方法,当发生器终结时,还会自动抛出 StopIteration 异常。综上所述,这些功能使得编写一个正规函数成为创建迭代器的最简单方法。
Ⅹ python迭代器和生成器的区别
这个的区别就是在使用的过程当中啊,它生成的旗舰是不一样的。