列表生成器混淆

时间:2014-07-23 21:14:11

标签: python list iterator generator

一直在读Pep-0289。它提到了

sum(x*x for x in range(10))

将节省内存:

sum([x*x for x in range(10)])

我感到困惑的是range(10)不能一次生成整个列表的原因。有什么地方,如果你在for-each构造中抛出range(),它会自动成为迭代器吗?我认为答案是否定的,因为这是Python 2.x中的xrange()

继续沿着Pep说:

def __gen(exp):
    for x in exp:
        yield x**2
g = __gen(iter(range(10)))
print g.next()

在这里,他们使用iterrange(10)转换为迭代器。为什么在前面的示例中不需要iter[x for x in range(3)][x for x in iter(range(3))]是否以某种方式对待?

2 个答案:

答案 0 :(得分:1)

  

以某种方式[x for x in [1, 3, 4]][x for x in iter([1, 3, 4])]   对待它?

它们具有相同的效果,是的。这一行:

[x for x in [1, 3, 4]]

隐式调用列表的__iter__ method来获取迭代器。它相当于:

[x for x in [1, 3, 4].__iter__()]

这一行:

[x for x in iter([1, 3, 4])]

使用iter在列表上获取迭代器。它也相当于:

[x for x in [1, 3, 4].__iter__()]

除了它不必要地使用内置的iter函数来执行for ... in ...子句已经执行的操作。


更好地使用iter是通过可迭代的逐步控制迭代。以下是一个例子:

it = iter(iterable)
item = next(it)  # Get the first item in the iterator
while True:
    # code
    if condition:
        item = next(it)  # Advance the iterator only if condition is True

答案 1 :(得分:1)

range(10)会立即生成整个列表。但这不是节省内存的部分。

此:

sum(x*x for x in range(10))

基本上会计算(或多或少)如下:

  • cur_sum = 1 * 1
  • cur_sum = cur_sum + 2 * 2
  • ...
  • cur_sum = cur_sum + 9 * 9

那就是它会单独计算每个,并且随着它的总和而计算

以下内容:

sum([x*x for x in range(10)])

而是首先创建一个完整的列表:

  • [1 * 1,2 * 2,3 * 3 ... 9 * 9]

然后做总和。