Python `for`语法:块代码与单行生成器表达式

38

我熟悉块代码上下文中的for循环。例如:

for c in "word":
    print c

我刚刚看到一些使用 for 的例子与通常不同。它们不是以 for 语句开头,而是在表达式的结尾处标记它(并且不涉及缩进的代码块)。例如:

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

能否有人指引我到一些说明使用for的文档?我找到了一些示例,但找不到解释。我找到的所有关于for的文档都描述了之前的用法(块代码示例)。我甚至不确定如何称呼这种用法,所以如果我的问题标题不清楚,我很抱歉。

4个回答

32
你所指的是 Python 中的生成器 Generator。请查看以下链接:

请参阅文档:Generator Expression,其中包含您提交的示例

从文档中可以了解到:

生成器是创建迭代器的一种简单而强大的工具。它们与普通函数类似,但在想要返回数据时使用 yield 语句。每次调用 next() 时,生成器会从上一次离开的地方继续执行(它会记住所有的数据值和上次执行的语句)。

生成器类似于使用 方括号List Comprehension,但它们更加节省内存。它们不会一次性地返回完整的 list 结果,而是返回生成器对象。每次在 generator 对象上调用 next() 时,生成器会使用 yield 返回下一个值。
对于上面的代码,List Comprehension 如下所示:-

[x * x for x in range(10)]
您还可以在 for 循环结束时添加条件来过滤结果。
[x * x for x in range(10) if x % 2 != 0]

如果这个数字不能被2整除,那么这将返回在1到5范围内的一个数字列表乘以2。

使用yield表现出生成器的例子可以是:

def city_generator():
    yield("Konstanz")
    yield("Zurich")
    yield("Schaffhausen")
    yield("Stuttgart")

>>> x = city_generator()
>>> x.next()
Konstanz
>>> x.next()
Zurich
>>> x.next()
Schaffhausen
>>> x.next()
Stuttgart
>>> x.next()
Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
StopIteration

所以你可以看到,每次调用 next() 都会执行 generator 中的下一个 yield(),并在最后抛出 StopIteration


1
生成器和列表推导式看起来非常相似:[x*x for x in range(10)]。您还可以包含一个条件来过滤结果:[x*x for x in range(10) if x % 2 == 0 or x % 3 == 0] - dave mankoff

9
那些是生成器表达式,它们与列表推导有关。
列表推导允许轻松创建列表。例如,如果您想创建一个完美平方数的列表,可以这样做:
>>> squares = []
>>> for x in range(10):
...     squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

但是你可以使用列表推导式:

squares = [x**2 for x in range(10)]

生成器表达式类似于列表推导式,不同之处在于它们返回一个生成器对象而不是列表。您可以以类似于列表推导式的方式迭代此生成器对象,但是如果您在列表推导式中创建列表,则不必一次性将整个列表存储在内存中。

0

0
你的具体示例被称为生成器表达式列表推导式, 字典推导式, 和 集合推导式 在意义上类似(结果类型不同,生成器表达式是惰性的),并且具有相同的语法,除了在其他种括号中,并且在字典推导式的情况下具有expr1: expr2而不是单个表达式(在您的示例中是x*x)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接