如何更好地理解Python迭代器和生成器
当一个log文件有很多行(maybe几万行)的时候,用cat ,你就会发现屏幕不停的刷刷刷,你怎么看?
so,这时候你需要用more来一页一页的阅读。
同样的道理,当文件被读入到内存时候,如果数据太大,会导致内存被占用过多。这时候需要一个像more的功能一次读取一点,这个就是迭代的功能。
那么怎么样才能有这样的功能存在呢?这就是生成器的作用。让cat aa.txt通过生成器变成more aa.txt的效果。
iamlaosong文
我们在用for
...
in
...语句循环时,in后面跟随的对象要求是可迭代对象,即可以直接作用于for循环的对象统称为可迭代对象(iterable),如list、tuple、dict、set、str等。
可迭代对象是实现了__iter__()方法的对象,而迭代器(iterator)则是实现了__iter__()和__next__()方法的对象,可以显示地获取下一个元素。这种可以被next调用并不断返回下一个值的对象称为迭代器。迭代器一定是可迭代对象,反过来则不一定成立。用iter()函数可以把list、dict、str等iterable变成iterator,例如:
bb=[x
for
x
in
range(10)]
cc=iter(bb)
cc.next()
循环变量的值其实可以看着是一次次用next取值的过程,每取一个值,做一次处理。list等对象用于循环实际上可以看着是用iter()方法产生一个迭代器,然后循环取值。
生成器(generator)就是一个能返回迭代器的函数,其实就是定义一个迭代算法,可以理解为一个特殊的迭代器。调用这个函数就得到一个迭代器,生成器中的yield相当于一个断点,执行到此返回一个值后暂停,从而实现next取值。
迭代器
迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址。迭代器修改了常规指针的接口,所谓迭代器是一种概念上的抽象:那些行为上像迭代器的东西都可以叫做迭代器。然而迭代器有很多不同的能力,它可以把抽象容器和通用算法有机的统一起来。
迭代器提供一些基本操作符:*、++、==、!=、=。这些操作和C/C++“操作array元素”时的指针接口一致。不同之处在于,迭代器是个所谓的复杂的指针,具有遍历复杂数据结构的能力。其下层运行机制取决于其所遍历的数据结构。因此,每一种容器型别都必须提供自己的迭代器。事实上每一种容器都将其迭代器以嵌套的方式定义于内部。因此各种迭代器的接口相同,型号却不同。这直接导出了泛型程序设计的概念:所有操作行为都使用相同接口,虽然它们的型别不同。
迭代器使开发人员能够在类或结构中支持foreach迭代,而不必整个实现IEnumerable或者IEnumerator接口。只需提供一个迭代器,即可遍历类中的数据结构。当编译器检测到迭代器时,将自动生成IEnumerable接口或者IEnumerator接口的Current,MoveNext和Dispose方法。
生成器
生成器是一次生成一个值的特殊类型函数。可以将其视为可恢复函数。调用该函数将返回一个可用于生成连续 x 值的生成器【Generator】
简单的说就是在函数的执行过程中,yield语句会把你需要的值返回给调用生成器的地方,然后退出函数,下一次调用生成器函数的时候又从上次中断的地方开始执行,而生成器内的所有变量参数都会被保存下来供下一次使用。
我来举例:
当一个txt文件有几万行的时候,你是用cat ,会发现屏幕不停的刷不停的刷,影响你正常阅读。
这时候你需要使用more来一页一页阅读。
同样的道理,当文件被读入到内存时候,如果数据太大,会导致内存被占用过多。这时候需要一个向more的功能一次读取一点,这个就是迭代器的功能。
那么怎么样才能有这样的功能存在呢?这就是生成器的作用。让cat aa.txt通过生成器变成more aa.txt的效果。
在Python中,有些名称会在前后加上两个下划线,这种拼写表示名字有特殊含义。所以绝不要在自己的程序中使用这种名字。
1. __init__方法
Python 类中有默认的构造函数__init__我们可以覆盖它来试试。如下:
class FooBar:
def __init__(self): self.somevar=42 f=FooBar() print f.somevar
我们修改一下如下:
class FooBar:
def __init__(self,value=42): self.somevar=value f=FooBar("what's this?")
print f.somevar
输出如下:
what's this?
2. 重写方法
如果一个方法在B类的一个实例中被调用,但在B类中没有找到方法,那么就会在超类A里面找。 如下所示:
class A:
def hello(self):
print "hello ,I.m A" class B(A): pass
a=A() b=B() a.hello() b.hello()
输出如下:
hello ,I.m A hello ,I.m A
B类没有定义自己的方法hello调用的是父类的hello方法。 如果进行重写这个方法,如下:
class A:
def hello(self):
print "hello ,I.m A" class B(A): pass
def hello(self): print "Hello,I'm B" a=A() b=B() a.hello() b.hello()
输出如下:
hello ,I.m A Hello,I'm B
3. 使用Super函数
我看来看下个例子如下:
class Bird:
def __init__(self): self.hungry=True def eat(self): if self.hungry: print 'Aaah...' self.hungry=False else:
print "No,thansk"
class SongBird(Bird): def __init__(self): self.sound='Squawk!'
def sing(self): print self.sound
sb=SongBird() sb.sing() sb.eat()
运行如下:
Squawk!
Traceback (most recent call last):
AttributeError: SongBird instance has no attribute 'hungry'
没有hungry属性。
没有得到父类的属性,需要用到Super函数,处理后如下:
from _pyio import __metaclass__ __metaclass__=type class Bird:
def __init__(self): self.hungry=True def eat(self): if self.hungry: print 'Aaah...' self.hungry=False else:
print "No,thansk"
class SongBird(Bird): def __init__(self): # Bird.__init__(self)
super(SongBird,self).__init__() self.sound='Squawk!' def sing(self): print self.sound
sb=SongBird() sb.sing() sb.eat()
运行如下:
Squawk! Aaah...
迭代器是访问集合元素的一种方式。迭代器对象从集合的第一个元素开始访问,知道所有的元素被访问完结束。迭代器只能往前不会后退,不过这也没什么,因为人们很少在迭代途中往后退。
使用迭代器的优点
对于原生支持随机访问的数据结构(如tuple、list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值)。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。
另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等。
迭代器更大的功劳是提供了一个统一的访问集合的接口,只要定义了__iter__()方法对象,就可以使用迭代器访问。
迭代器有两个基本的方法
next方法:返回迭代器的下一个元素
__iter__方法:返回迭代器对象本身
简单地讲,yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不是一个普通函数,Python 解释器会将其视为一个 generator,调用 fab(5) 不会执行fab 函数,而是返回一个 iterable 对象!在 for 循环执行时,每次循环都会执行 fab 函数内部的代码,执行到 yield b 时,fab 函数就返回一个迭代值,下次迭代时,代码从 yield b 的下一条语句继续执行,而函数的本地变量看起来和上次中断执行前是完全一样的,于是函数继续执行,直到再次遇到 yield。看起来就好像一个函数在正常执行的过程中被 yield 中断了数次,每次中断都会通过 yield 返回当前的迭代值。
对于原生支持随机访问的数据结构(如tuple、list),迭代器和经典for循环的索引访问相比并无优势,反而丢失了索引值(可以使用内建函数enumerate()找回这个索引值)。但对于无法随机访问的数据结构(比如set)而言,迭代器是唯一的访问元素的方式。
另外,迭代器的一大优点是不要求事先准备好整个迭代过程中所有的元素。迭代器仅仅在迭代到某个元素时才计算该元素,而在这之前或之后,元素可以不存在或者被销毁。这个特点使得它特别适合用于遍历一些巨大的或是无限的集合,比如几个G的文件,或是斐波那契数列等等。
迭代器更大的功劳是提供了一个统一的访问集合的接口,只要定义了__iter__()方法对象,就可以使用迭代器访问。
描写春天的诗
等闲识得东风面,万紫千红总是春。《忆江南·江南好》【唐】白居易 江南好,风景旧曾谙。日出江花红胜火,春来江水绿如蓝。能不忆江南?江南忆,最忆是杭州。山寺月中寻桂子,郡亭枕上看潮头。何日更重游?江南忆,其次忆吴宫。吴酒一杯春竹叶,吴娃双舞醉芙蓉。早晚复相逢?
形容新叶的诗句有哪些
回答者:h2pyt 时间:2010-03-27 10:18:00 叶上初阳干宿雨,水面清圆,一一风荷举。江南可采莲,莲叶何田田。 慈姑叶烂别西湾,莲子花开不见还。莫听穿林打叶声,何妨吟啸且徐行。 停车坐爱枫林晚,霜叶红于二月花。荷叶罗裙一色裁,芙蓉向脸两边开。 一点残红影下,青山绿水白草红叶黄花。碧云天,黄叶地,秋色连波...
巫衫苯唑: 更好的理解python的迭代器和生成器,可以打个比方 ,赌场发牌的荷官算是一个不错的比喻.本来你需要自己去处理一堆牌(一个 collection),现在你有了这个对象,只要不断问他要“下一张”,他要是有自然会给你,没有就结束(StopIteration).
潍城区15860374528: Python中生成器和迭代器的区别 - ?
巫衫苯唑: 更好的理解python的迭代器和生成器,可以打个比方 ,赌场发牌的荷官算是一个不错的比喻. 本来你需要自己去处理一堆牌(一个 collection),现在你有了这个对象,只要不断问他要“下一张”,他要是有自然会给你,没有就结束(StopIteration).
潍城区15860374528: python 可迭代对象和迭代器的区别 - ?
巫衫苯唑: Iamlaosong文 我们在用for ... in ...语句循环时,in后面跟随的对象要求是可迭代对象,即可以直接作用于for循环的对象统称为可迭代对象(Iterable),如list、tuple、dict、set、str等. 可迭代对象是实现了__iter__()方法的对象,而迭代器(...
潍城区15860374528: python生成器和迭代器的区别 - ?
巫衫苯唑: 先说迭代器,对于string、list、dict、tuple等这类容器对象,使用for循环遍历是很方便的.在后台for语句对容器对象调用iter()函数,iter()是python的内置函数.iter()会返回一个定义了next()方法的迭代器对象
潍城区15860374528: python中迭代器和生成器的区别 - ?
巫衫苯唑: 对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的.在后台for语句对容器对象调用iter()函数.iter()是Python内置函数.iter()会返回一个定义了next()方法的迭代器对象,它在容器中逐个访问容器内的元素.next()也是python内置函数.在没有后续元素时,next()会抛出一个StopIteration异常,通知for语句循环结束.
潍城区15860374528: Python中迭代器和生成器的区别与联系 - ?
巫衫苯唑: 用代码说明下 def miter(): return list(range(10)) def myield(): for i in range(10): yield i print(miter()) print(myield())输出是 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]<generator object myield at 0x000002A0118740F8>不知道,你发现什么东西没?迭代器,是直接返回...
潍城区15860374528: python中的迭代器有什么用 - ?
巫衫苯唑: 什么是迭代 可以直接作用于for循环的对象统称为可迭代对象(Iterable).可以被next()函数调用并不断返回下一个值的对象称为迭代器(Iterator).所有的Iterable均可以通过内置函数iter()来转变为Iterator.对迭代器来讲,有一个__next ...
潍城区15860374528: python 迭代器和生成器的区别 - ?
巫衫苯唑: Num01–>迭代器 定义: 对于list、string、tuple、dict等这些容器对象,使用for循环遍历是很方便的.在后台for语句对容器对象调用iter()函数.iter()是python内置函数. iter()函数会返回一个定义了next()方法的迭代器对象,它在容器...
潍城区15860374528: [python]关于python的迭代器和列表推导的问题 - ?
巫衫苯唑: 这句相当于 count = 0 a = [] while True: count += 1 if count 显然是个死循环 问题出在你的迭代类里没有终止条件 class numCounter: 'this is a class to simulate a counter' def __init__(self,max=10): self.max = max self.count=0 def __next__(self): self....
潍城区15860374528: python的迭代器为什么一定要实现 - ?
巫衫苯唑: 这是个和多态有关的问题,Python中关于迭代有两个概念,第一个是Iterable,第二个是Iterator,协议规定Iterable的__iter__方法会返回一个Iterator, Iterator的__next__方法(Python 2里是next)会返回下一个迭代对象,如果迭代结束则抛出...