python迭代器和生成器

Python迭代器和生成器

迭代器的底层机制

下面一段代码向我们演示了迭代期间发生的基本细节

items = [1, 2, 3]
it = iter(items)
print(next(it))
# 输出1
print(next(it))
# 输出2
print(next(it))
# 输出3
print(next(it))
# 报了一个异样如下
# Traceback (most recent call last):
# 	File "<stdin>", line 1, in <module>
# StopIteration 

从上面的列子可以看出,对于一个迭代器,当调用next()函数的时候,会将序列里面的元素一个一个返回,当序列里面的元素已经迭代完成的时候,再去调用next()就会抛出一个StopIteration的异常。

所以我们可以不使用for循环,通过以下的方式来手动遍历一个迭代器

with open("demo.txt") as fp:
	try:
		while True:
			line = next(fp)
			print(line, end="")
	except StopIteration:
		pass

通常来讲,StopIteration用来指示迭代的结尾。你还可以通过返回一个制定值来标记结尾,比如None。

with open("demo.txt") as fp:
	while True:
		line = next(fp, None)
		if line is None:
			break
		print(line, end="")

生成器

下面是一个生成器函数,用来生产某个范围内的数字。

def frange(start, stop, increment):
	x = start
	while x < stop:
		yield x
		x += increment

你可以使用for循环来使用生面这个函数

for n in frange(0, 4, 0.5):
	print(n)
# 输出
# 0
# 0.5
# 1
# 1.5
# ...
list(frange(0, 3, 1))
# [0, 1, 2]

一个函数中如果有yield语句,那么这个函数就是一个生成器函数。和普通函数不同的是,生成器只能用于迭代操作。
下面这个函数向你展示了生成器函数的底层工作机制

def countdown(n):
	print("Starting to count from", n)
	while n > 0:
		yield n
		n -= 1
	print("Done!")

c = countdown(3)
print(next(c))
# 输出
# Starting to count from 3
# 3
print(next(c))
# 2
print(next(c))
# 1
print(next(c))
# Done!
# Traceback (most recent call last):
# 	File "<stdin>", line 1, in <module>
# StopIteration 

自己对于yield关键字的简单理解

我们可以将yield简单的裂解成一个return,但是它和return有一定的区别。例如上面的那个countdown的列子,当我们调用一次next()
countdown()函数会执行,直到遇见yield这个关键字,yield会将器后面的n返回,并停在这里。当第二次调用next的时候函数会继续执行,直到下一次遇见yield。依次类推,直到所有的yield都执行完,最后抛出一个异常。
更多更加详细的关于yield的理解大家可以参考下面的文章
https://www.jianshu.com/p/9dd355ab4e5d

上一篇:理解迭代器,生成器,yield,可迭代对象


下一篇:generator 和 yield的使用