Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/320.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 什么时候使用迭代器,什么时候使用生成器?_Python_Python 3.x - Fatal编程技术网

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

我读了一些关于迭代器和生成器之间差异的问题。但我不明白你什么时候应该选择一个?你知道一个比另一个好的例子(简单的,现实生活中的例子)吗?谢谢。

迭代器提供了在现有数据结构上进行迭代的有效方法

生成器提供了动态生成序列元素的有效方法

迭代器示例 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
在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.x
range
和Python2.x
xrange
不是生成器。它们是懒惰的序列。生成器的定义是生成迭代器的函数。为了理解这个概念,它们可以100%被认为是生成器,因为这些内置组件很可能是OP熟悉的,所以我使用了它们——但我会用一个合适的生成器更新我的帖子。