本文目录一览:
Python中的迭代器与可迭代:iter()和next()
一种自动迭代的更优雅的实现是使用 for循环
在Python中,迭代器(Iterator)和可迭代(iterable)的区别是,迭代器支持 iter()
和 next()
方法;可迭代支持 iter()
方法。可迭代只能在for循环中获得元素,迭代器还可以用 next()
方法获取元素。
list
、tuple
、map
、dict
都是可迭代,但不是迭代器;这些数据的大小是确定的;迭代器不是,迭代器不知道要执行多少次,所以可以理解为不知道有多少个元素,每调用一次 next()
,就会往下走一步。
凡是可以 for
循环的,都是 Iterable
凡是可以 next()
的,都是 Iterator
Python中的迭代器是什么
迭代器 迭代是访问集合元素的一种方式。迭代器是一个可以记住遍历的位置的对象。迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束。迭代器只能往前不会后退。
1. 可迭代对象
可以直接作用于 for
循环的数据类型有以下几种:
- 一类是集合数据类型,如
list
、tuple
、dict
、set
、str
等; - 一类是
generator
,包括生成器和带yield
的generator function
。 这些可以直接作用于for
循环的对象统称为可迭代对象:Iterable
。
2. 判断是否可以迭代
可以使用 isinstance()
判断一个对象是否是 Iterable
对象:
而生成器不但可以作用于 for
循环,还可以被 next()
函数不断调用并返回下一个值,直到最后抛出 StopIteration
错误表示无法继续返回下一个值了。
相关推荐:《Python视频教程》
3. 迭代器
可以被 next()
函数调用并不断返回下一个值的对象称为迭代器:Iterator
。
4. iter()
函数
生成器都是 Iterator
对象,但 list
、dict
、str
虽然是 Iterable
,却不是 Iterator
。
把 list
、dict
、str
等 Iterable
变成 Iterator
可以使用 iter()
函数:
运行结果:
总结:
- 凡是可作用于
for
循环的对象都是Iterable
类型; - 凡是可作用于
next()
函数的对象都是Iterator
类型; - 集合数据类型如
list
、dict
、str
等是Iterable
但不是Iterator
,不过可以通过iter()
函数获得一个Iterator
对象; - 目的是在使用集合的时候,减少占用的内容。 相关推荐:
- 三分钟看懂什么是Python生成器
Python什么是迭代器
我们在用 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
取值。
Python中的“迭代”详解
迭代器模式:一种惰性获取数据项的方式,即按需一次获取一个数据项。
所有序列都是可以迭代的。我们接下来要实现一个 Sentence
(句子)类,我们向这个类的构造方法传入包含一些文本的字符串,然后可以逐个单词迭代。
接下来测试 Sentence
实例能否迭代:
序列可以迭代的原因:
iter()
:解释器需要迭代对象x
时,会自动调用iter(x)
。- 内置的
iter
函数有以下作用:- 由于序列都实现了
__getitem__
方法,所以都可以迭代。 - 可迭代对象:使用内置函数
iter()
可以获取迭代器的对象。 - 与迭代器的关系:Python 从可迭代对象中获取迭代器。
下面用
for
循环迭代一个字符串,这里字符串'abc'
是可迭代的对象,用for
循环迭代时是有生成器,只是 Python 隐藏了。 如果没有for
语句,使用while
循环模拟,要写成下面这样:
- 由于序列都实现了
s = 'abc'
it = iter(s)
while True:
try:
print(next(it))
except StopIteration:
break
Python 内部会处理 for
循环和其他迭代上下文(如列表推导,元组拆包等等)中的 StopIteration
异常。
标准的迭代器接口有两个方法:
__next__
:返回下一个可用的元素,如果没有元素了,抛出StopIteration
异常。__iter__
:返回self
,以便在需要使用可迭代对象的地方使用迭代器,如for
循环中。 迭代器:实现了无参数的__next__
方法,返回序列中的下一个元素;如果没有元素了,那么抛出StopIteration
异常。Python 中的迭代器还实现了__iter__
方法,因此迭代器也可以迭代。 接下来使用迭代器模式实现Sentence
类: 注意,不要在Sentence
类中实现__next__
方法,让Sentence
实例既是可迭代对象,也是自身的迭代器。 为了“支持多种遍历”,必须能从同一个可迭代的实例中获取多个独立的迭代器,而且各个迭代器要能维护自身的内部状态,因此这一模式正确的实现方式是,每次调用iter(my_iterable)
都新建一个独立的迭代器。 所以总结下来就是: 实现相同功能,但却符合 Python 习惯的方式是,用生成器函数代替SentenceIterator
类。 只要 Python 函数的定义体中有yield
关键字,该函数就是生成器函数。调用生成器函数,就会返回一个生成器对象。 生成器函数会创建一个生成器对象,包装生成器函数的定义体,把生成器传给next(...)
函数时,生成器函数会向前,执行函数定义体中的下一个yield
语句,返回产出的值,并在函数定义体的当前位置暂停。最终,函数的定义体返回时,外层的生成器对象会抛出StopIteration
异常,这一点与迭代器协议一致。 如今这一版Sentence
类相较之前简短多了,但是还不够慵懒。惰性,是如今人们认为最好的特质。惰性实现是指尽可能延后生成值,这样做能节省内存,或许还能避免做无用的处理。 目前实现的几版Sentence
类都不具有惰性,因为__init__
方法急迫的构建好了文本中的单词列表,然后将其绑定到self.words
属性上。这样就得处理整个文本,列表使用的内存量可能与文本本身一样多(或许更多,取决于文本中有多少非单词字符)。re.finditer
函数是re.findall
函数的惰性版本,返回的是一个生成器,按需生成re.MatchObject
实例。我们可以使用这个函数来让Sentence
类变得懒惰,即只在需要时才生成下一个单词。 标准库提供了很多生成器函数,有用于逐行迭代纯文本文件的对象,还有出色的os.walk
函数等等。本节专注于通用的函数:参数为任意的可迭代对象,返回值是生成器,用于生成选中的、计算出的和重新排列的元素。 第一组是用于过滤的生成器函数:从输入的可迭代对象中产出元素的子集,而且不修改元素本身。这种函数大多数都接受一个断言参数(predicate
),这个参数是个布尔函数,有一个参数,会应用到输入中的每个元素上,用于判断元素是否包含在输出中。 以下为这些函数的演示: 第二组是用于映射的生成器函数:在输入的单个/多个可迭代对象中的各个元素上做计算,然后返回结果。 以下为这些函数的用法: 第三组是用于合并的生成器函数,这些函数都可以从输入的多个可迭代对象中产出元素。 以下为演示: 第四组生成器函数用于从一个元素中产出多个值,扩展输入的可迭代对象。 以下为演示: 第五组生成器函数用于产出输入的可迭代对象中的全部元素,不过会以某种方式重新排列。 下面的函数都接受一个可迭代的对象,然后返回单个结果,这种函数叫“归约函数”、“合拢函数”或“累加函数”。其实,这些内置函数都可以用functools.reduce
函数实现,但内置更加方便,而且还有一些优点。 参考教程:- 《流畅的python》 P330 - 363
python中的迭代器的理解?
9.9. 迭代器
现在你可能注意到大多数容器对象都可以用 for
遍历:
for element in [1, 2, 3]:
print(element)
for element in (1, 2, 3):
print(element)
for key in {'one':1, 'two':2}:
print(key)
for char in "123":
print(char)
for line in open("myfile.txt"):
print(line, end='')
这种形式的访问清晰、简洁、方便。迭代器的用法在 Python 中普遍而且统一。在后台,for
语句在容器对象中调用 iter()
。该函数返回一个定义了 __next__()
方法的迭代器对象,它在容器中逐一访问元素。没有后续的元素时,__next__()
抛出一个 StopIteration
异常通知 for
语句循环结束。你可以使用内建的 next()
函数调用 __next__()
方法;以下是其工作原理的示例:
s = 'abc'
it = iter(s)
it
next(it)
# 'a'
next(it)
# 'b'
next(it)
# 'c'
next(it)
# Traceback (most recent call last):
# File "<stdin>", line 1, in ?
# next(it)
# StopIteration
了解了迭代器协议的后台机制,就可以很容易的给自己的类添加迭代器行为。定义一个 __iter__()
方法,使其返回一个带有 __next__()
方法的对象。如果这个类已经定义了 __next__()
,那么 __iter__()
只需要返回 self
。