Python的迭代器和生成器:仍未完全理解

时间:2015-11-25 11:16:52

标签: python python-3.x iterator generator

import random

my_list = [random.randint(3, 100) for i in range(4)]

def is_even(some_list):
    for i in some_list:
        if i % 2 == 0:
            yield True
        else:
            yield False

print(my_list)
print(list(is_even(my_list)))

>>> [94, 53, 27, 42]
>>> [True, False, False, True]

似乎我仍然不完全理解这个概念。在每次迭代时,is_even函数会相应地生成TrueFalse。我不知道这些“收益率”是如何积累的。 (或者,我没有看到它们如何在每次迭代结束时附加到最终列表。例如,在给定的示例中,第一次迭代产生True,然后第二次迭代开始。保留True值?)那里究竟发生了什么?

4 个答案:

答案 0 :(得分:2)

回答你的问题:积累魔法发生在list构造函数中 - 实际上,将项目累积到列表中就是它的工作。当你写:

print(list(is_even(my_list)))

is_even(...)返回的对象有一个next()方法,它提供生成器产生的下一个值,或者在没有更多值可用时引发异常。 list函数是将这些值累积到列表中的函数,最终返回。

你可以想象list是一个像这样定义的函数:

def list(iter):
    accum = []
    # the following loop is an approximate expansion of
    # for item in iter: accum.append(item)
    while 1:
        try:
            # get the next yielded value from generator
            item = iter.next()
        except StopIteration:
            # no more values
            break
        accum.append(item)
    return accum

在你的情况下,list给出了一个生成器,for循环耗尽了生成器并将各个元素累积在一个保留在引擎盖下的临时列表中。正是上面实现中的临时列表accum,它保存了第一个True值,并继续存储后续的值。生成器耗尽后,整个累积列表将返回给调用者。

答案 1 :(得分:0)

我想我理解你的意思:

每次运行is_even,它都会检查列表中的每个数字并返回True或false(因为我确定您已经知道了)。当您使用' print(list(is_even(my_list)))'这个过程非常简单 - 您正在创建一个函数' is_even'返回的每个结果的列表,其顺序与for循环处理它们的顺序相同。

希望这有所帮助。

答案 2 :(得分:0)

您可以将迭代器理解为一个列表,其中包含所有未填充的元素,直到您要求它们为止。如果你使用迭代器作为参数实例化一个列表,就像你在这条指令list(is_even(my_list))中所做的那样,你将立即将所有元素输出到内存中,这在使用迭代器时不是我们想要的,因为它更有效只有最后一个要检查的元素,而不是整个东西,对吗?所以尝试一次迭代一遍:

for item in iterator:

或使用next()方法。

答案 3 :(得分:0)

从开始的例子开始:

my_list = [random.randint(3, 100) for i in range(4)]

这是list comprehension的一个很好的例子。这只是一种更简洁的写作方式:

my_list = []
for i in range(4):
    my_list.append(random.randint(3, 100))

接下来,您定义generator function

def is_even(some_list):
    for i in some_list:
        if i % 2 == 0:
            yield True
        else:
            yield False

生成器函数的行为类似于迭代器。价值根据需要“产生”。您可以将其描绘为流式传输结果的功能

print(list(is_even(my_list)))

此时正在发生一些事情,让我们分开它们以便更好地了解正在发生的事情:

>>> g = is_even(my_list)

is_even(my_list)不会像您预期的那样返回列表,而是返回生成器

>>> g
... <generator object is_even at ...>
>>> type(g)
... generator

list构造接受iterable作为参数,generatoriterable。在构建实际列表时,您的产生的值实际上是在此步骤累积的:

>>> l = list(g)
>>> print(l)
... [True, False, False, True]