我阅读了一些关于迭代器和生成器之间区别的问题和答案。但是我不明白何时应该选择其中之一?您知道任何例子(简单的、现实生活中的)在某些情况下一个比另一个更好吗?谢谢。
我阅读了一些有关迭代器和生成器之间区别的问题和答案。但是我不明白何时应该选择其中之一?您是否知道任何例子(简单的、现实生活中的),其中一种方法比另一种方法更好?谢谢。我阅读了一些关于迭代器和生成器之间区别的问题和答案。但是我不明白何时应该选择其中之一?您知道任何例子(简单的、现实生活中的)在某些情况下一个比另一个更好吗?谢谢。
我阅读了一些有关迭代器和生成器之间区别的问题和答案。但是我不明白何时应该选择其中之一?您是否知道任何例子(简单的、现实生活中的),其中一种方法比另一种方法更好?谢谢。迭代器提供了在现有数据结构上进行迭代的高效方法。
生成器提供了即时生成序列元素的高效方法。
Python的文件阅读器可以用作迭代器。因此,您可能会使用以下内容来处理文件的一行:
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
)每次您要求一行时都会读取一行。
生成器可以即时生成序列元素。请考虑以下内容:
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
# Print the fibonacci sequence until some event occurs
for f in fib():
print(f)
if f > 100: break
在这里,我们使用in
语法来迭代生成器,并打印返回的值,直到我们得到一个大于100的值。
输出:
0 1 1 2 3 5 8 13 21 34 55 89 144
调用next()
我们也可以在生成器上调用next
(因为生成器是迭代器),以这种方式(生成并)访问值:
f = fib()
print(next(f)) # 0
print(next(f)) # 1
print(next(f)) # 1
print(next(f)) # 2
print(next(f)) # 3
然而,有更有说服力的生成器示例。这些通常采用"生成器表达式"的形式,这是一个相关概念(PEP-289)。
考虑以下内容:
first = any((expensive_thing(i) for i in range(100)))
在这里,我们正在创建一个生成器表达式:
(expensive_thing(i) for i in range(100))
any
。当可迭代对象的元素被确定为True
时,any
会立即返回True
。因此,当您将生成器函数传递给any
时,它只会调用expensive_thing(i)
尽可能少的次数来查找True
值。any
的列表推导进行比较:first = any([expensive_thing(i) for i in range(100)])
expensive_thing(i)
,首先,然后将100个元素的True
/False
值列表提供给any
,如果它找到一个True
-ish值,它将返回True
。expensive_thing(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
expensive_thing
引入了人为的延迟,以说明这两种方法之间的差异。第二种(列表推导式)方法需要更长的时间,因为expensive_thing
在所有100个索引处都被评估,而第一个方法只调用expensive_thing
直到找到一个True
值(i=11
)。range
和Python 2.x中的xrange
不是生成器。它们是惰性序列。生成器的定义是产生迭代器的函数。请参见https://docs.python.org/3/glossary.html#term-generator。 - user2555451