Python:如果迭代器是一个表达式,那么每次都计算它吗?

时间:2010-06-29 02:19:00

标签: python iterator loops

采用以下示例:

>>> for item in [i * 2 for i in range(1, 10)]:
    print item


2
4
6
8
10
12
14
16
18

每次循环计算[i * 2 for i in range(1, 10)],还是仅存储一次? (另外,表达式中该部分的正确名称是什么?)

我想要这样做的一个原因是我只希望循环中可以获得该列表理解的结果。

3 个答案:

答案 0 :(得分:5)

for i in <whatever>: <loopbody>的良好翻译,准确显示其对任何 <whatever>任何 <loopbody>的作用:

_aux = iter(<whatever>)
while True:
  try: i = next(_aux)
  except StopIteration: break
  <loopbody>

除了我在这里命名为_aux的伪变量实际上仍未命名。

因此,<whatever>总是只被评估一次(从中获取iter())并且生成的迭代器为next,直到它用完为止(除非有break<loopbody>)。

使用listcomp,正如您所使用的那样,评估会生成一个list对象(在您的代码示例中仍然未命名)。在非常相似的代码中:

for item in (i * 2 for i in range(1, 10)): ...

使用genexp而不是listcomp(在语法上,圆括号而不是listcomp的方括号),实际执行大部分工作的next()(推进i并加倍),而不是在构造时集中所有工作 - 这会占用较少的临时内存,并且如果循环体很可能提前break出来,可以节省时间,但除非在这种特殊条件下(非常紧张的内存或可能早期循环终止) )listcomp通常可以(通过一点点)更快。

答案 1 :(得分:3)

在这种情况下,您正在内存中构建一个列表,然后您正在迭代列表的内容,所以是的,它被计算一次并存储。这与做

没什么不同
i for i in [2,4,6,8]:
   print(i)

如果你这样做(i * 2 for x in xrange(1,10)),你会得到一个迭代器来评​​估每次迭代。

答案 2 :(得分:3)

expression list的所有成员计算一次,然后迭代。

在Python 2.x中,LC中使用的变量确实泄漏到父作用域中,但由于LC已经被评估,因此唯一可用的值是用于在结果列表中生成最终元素的值。