生成器表达式和括号

3
为什么生成器表达式中包含元组时需要使用圆括号,即括号?
((x, y)
 for x in range(10)
 for y in range(20))

替代

(x, y
 for x in range(10)
 for y in range(20))

SyntaxError: invalid syntax

2
后者有点含糊不清;开始像普通的元组,但在解析时后来却变成了生成器。(不仅适用于生成器,也适用于列表推导式) - tobias_k
是的 :) 我会接受这个答案 - Har
1个回答

4
后者有点模糊:它像普通元组一样开始,但在解析后变成生成器。当我们有超过两个元素时,可能会更加明显,例如 (1, 2, 3, 4, x for x in range(10))
这也可以在语法规范中看到:
generator_expression ::=  "(" expression comp_for ")"

expression最终转化为atom(等等其他情况)时

atom      ::=  identifier | literal | enclosure
enclosure ::=  parenth_form | list_display
               | generator_expression | dict_display | set_display
               | string_conversion | yield_atom
parenth_form ::=  "(" [expression_list] ")"
expression_list ::=  expression ( "," expression )* [","]

换句话说,一个像 x, y 这样的表达式列表必须用括号括起来(除了在赋值语句中,如 a = b, c,可以直接使用)。
assignment_stmt ::=  (target_list "=")+ (expression_list | yield_expression)

(不仅仅适用于生成器,也适用于列表推导式,同时在Python 3中也适用。)

@Chris_Rands:从检查来看很明显,但解析器并不是直接进行检查,它们逐个读取输入的标记,并在语法中寻找模式匹配。 - Ignacio Vazquez-Abrams
1
@IgnacioVazquez-Abrams 我理解你的观点,但是通过解析器检测forin关键字应该很容易吧?我经常会不小心写出像[a, int(b) for a, b in zip(lst1,lst2)]这样的代码,Python会有所不同吗? - Chris_Rands
@IgnacioVazquez-Abrams 1和2也可用于返回语句或for循环中,例如:返回1,2和在persons中使用年龄和姓名。 - Har
1
@Chris_Rands:问题是,一旦解析器检测到这些内容,它就必须通过标记回溯来重新解析输入。这使得解析器变得更慢、更复杂。 - Ignacio Vazquez-Abrams
我猜测一个歧义是由于很难区分“列表显示”和生成器,因为它们共享相同的初始语法。[1,2,3,4]与[1,2,3,4 for x in range(10)],尽管可以说你可以做更多的工作,并期望一个“for”标记来使其成为生成器,如果没有for存在,则为列表显示,因此Ignacio提到了回溯。 - Har
显示剩余2条评论

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