是否有理由在for
循环中循环隐式元组是正常的,但是当你在理解中执行它时会出现语法错误?
例如:
for i in 'a','b','c':
print(i)
'a'
'b'
'c'
但是理解:
>>> [i for i in 'a','b','c']
File "<stdin>", line 1
[i for i in 'a','b','c']
^
SyntaxError: invalid syntax
这有什么理由吗?我不确定正确的术语,所以我的搜索没有任何用处。
更新
根据评论,此语法 对Python 2.x有效,但对Python 3.x无效。
答案 0 :(得分:23)
这在Python3中有所改变,主要是为了使列表推导与生成器表达式更加一致。
使用for循环和列表推导,使用没有括号的元组时没有歧义,因为前者始终以冒号结束,后者由结束括号或for/if
关键字终止。
但是,生成器表达式的部分设计要求它们可以“裸”用作函数参数:
>>> list(i for i in range(3))
[0, 1, 2]
会为未加密码的元组创建一些歧义,因为任何逗号都可能引入一个新参数:
>>> list(i for i in 0, 1, 2)
File "<stdin>", line 1
SyntaxError: Generator expression must be parenthesized if not sole argument
因此,元组必须始终在生成器表达式中用括号括起来,同样的限制现在也适用于列表推导以保持一致性。
PS:
Guido van Rossum撰写了一篇文章,在他的Python博客博客中阐述了有关该主题的所有细节:
答案 1 :(得分:3)
因为第一个代码中的for i in
与第二个代码中的for i in
的语法结构不同。
第一种情况是a for
statement, which has the grammar:
for_stmt ::= "for" target_list "in" expression_list ":" suite
["else" ":" suite]
'a', 'b', 'c'
绝对是expression_list
,因此可以解决问题。
然而,在第二种情况下,方括号内的for
强制将代码解释为列表推导,而在Python 3中,list comprehensions must have the syntax:
comprehension ::= expression comp_for
comp_for ::= "for" target_list "in" or_test [comp_iter]
comp_iter ::= comp_for | comp_if
comp_if ::= "if" expression_nocond [comp_iter]
请注意,in
之后的部分必须是or_test
,但逗号分隔的表达式会创建expression lists,而表达式列表不能是or_test
---或者换句话说,or
的优先级高于逗号。 Python因此认为理解以逗号结束,因此列表的三个元素是:
i for i in 'a'
'b'
'c'
(除非你将i for i in 'a'
括在括号中)显然是无效的。
至于为什么这在Python 2中有用......我还在寻找。
答案 2 :(得分:0)
我认为问题在于:在后一种情况下,你在迭代哪些对象并不是那么明显:
>>> [i for i in ('a','b','c')]
['a', 'b', 'c']
元素之间的边界在哪里?它是一个由3个元素组成的数组:生成器和2个整数?像这样:
>>> [(i for i in 'a'),'b','c']
[<generator object <genexpr> at 0x10cefeeb8>, 'b', 'c']
for
没有这种歧义 - 所以它不需要括号。