Python 什么时候使用迭代器,什么时候使用生成器?
我读了一些关于迭代器和生成器之间差异的问题。但我不明白你什么时候应该选择一个?你知道一个比另一个好的例子(简单的,现实生活中的例子)吗?谢谢。迭代器提供了在现有数据结构上进行迭代的有效方法 生成器提供了动态生成序列元素的有效方法 迭代器示例 Python的文件读取器可以用作迭代器。因此,您可以使用什么来处理文件的一行:Python 什么时候使用迭代器,什么时候使用生成器?,python,python-3.x,Python,Python 3.x,我读了一些关于迭代器和生成器之间差异的问题。但我不明白你什么时候应该选择一个?你知道一个比另一个好的例子(简单的,现实生活中的例子)吗?谢谢。迭代器提供了在现有数据结构上进行迭代的有效方法 生成器提供了动态生成序列元素的有效方法 迭代器示例 Python的文件读取器可以用作迭代器。因此,您可以使用什么来处理文件的一行: with open('file.txt', 'rb') as fh: lines = fh.readlines() # this reads the entire fi
with open('file.txt', 'rb') as fh:
lines = fh.readlines() # this reads the entire file into lines, now
for line in lines:
process(line) # something to be done on each line
您可以使用迭代器更有效地实现
with open('file.txt', 'rb') as fh:
for line in fh: # this will only read as much as needed, each time
process(line)
其优点在于,在第二个示例中,您没有将整个文件读入内存,而是迭代一系列行。相反,读取器(BufferedReader
在Python3中)每次都在读一行,每次你都要读一行
生成器示例
生成器动态生成序列的元素。考虑以下事项:
def fib():
idx = 0
vals = [0,1]
while True:
# If we need to compute a new value, do so on the fly
if len(vals) <= idx: vals.append(vals[-1] + vals[-2])
yield vals[idx]
idx += 1
first = any((expensive_thing(i) for i in range(100)))
在这里,我们使用语法中的对生成器进行迭代,并打印返回的值,直到得到大于100的值
输出:
0
1
1
2
3
5
8
13
21
34
55
89
144
然而,还有更具说服力的发电机例子。这些通常以相关概念()的形式出现
考虑如下情况:
def fib():
idx = 0
vals = [0,1]
while True:
# If we need to compute a new value, do so on the fly
if len(vals) <= idx: vals.append(vals[-1] + vals[-2])
yield vals[idx]
idx += 1
first = any((expensive_thing(i) for i in range(100)))
在这里,我们创建一个生成器表达式:
(expensive_thing(i) for i in range(100))
并将其传递给任何
内置函数<一旦iterable的某个元素被确定为True
,code>any
将返回True
。因此,当您将生成器函数传递给any
时,它只会调用昂贵的东西(i)
查找真值所需的次数
将此与使用传递给any
的列表进行比较:
first = any([expensive_thing(i) for i in range(100)])
在这种情况下,将为i
的所有值调用i
,首先,然后将True
/False
值的100个元素列表赋予任何
,如果找到True
值,则返回True
但是如果昂贵的东西(0)
返回True
,显然更好的方法只是评估它,测试它,然后停在那里。生成器允许您这样做,而列表理解之类的东西则不允许
考虑以下示例,说明使用生成器表达式优于列表理解的优势:
import time
def expensive_thing(n):
time.sleep(0.1)
return 10 < n < 20
# Find first True value, by using a generator expression
t0 = time.time()
print( any((expensive_thing(i) for i in range(100))) )
t1 = time.time()
td1 = t1-t0
# Find first True value, by using a list comprehension
t0 = time.time()
print( any([expensive_thing(i) for i in range(100)]) )
t1 = time.time()
td2 = t1-t0
print("TD 1:", td1) # TD 1: 1.213068962097168
print("TD 2:", td2) # TD 2: 10.000572204589844
导入时间
def昂贵的东西(n):
睡眠时间(0.1)
返回10
函数昂贵的东西
引入了一个人工延迟来说明这两种方法之间的区别。第二种(列表理解)方法需要更长的时间,因为昂贵的东西
在所有100个索引上进行评估,而第一种方法只调用昂贵的东西
,直到找到真值(i=11
).读了这篇文章后,你到底不明白什么?我是python新手。大多数事情对我来说都是新的。noob的简单示例比编写“Python的生成器提供了一种实现迭代器协议的便捷方式”或其他技术术语要好。需要掌握一些技术术语的知识,你知道的越多,你就能更好地找到问题的答案并提出问题,以获得更多更好的答案。要回答您的问题,请查看interator vs generator问题的帖子。正如我在那篇文章中所解释的(得票最多但仍不被接受:-)差不多五年前的答案,所有的生成器都是迭代器(尽管不是相反),所以您的问题完全没有任何意义——比如问“我什么时候应该吃意大利面而不是意大利面?”当意大利面是意大利面的一个例子(例如,特例),或者问“我应该买一只拉布拉多犬还是一只狗”(因为拉布拉多犬是一种狗),等等。简明扼要,genexp->generator。可扩展性、灵活性->迭代器。Python3.xrange
和Python2.xxrange
不是生成器。它们是懒惰的序列。生成器的定义是生成迭代器的函数。为了理解这个概念,它们可以100%被认为是生成器,因为这些内置组件很可能是OP熟悉的,所以我使用了它们——但我会用一个合适的生成器更新我的帖子。