为什么列表中的元组需要括号?

2024-10-02 00:41:01 发布

您现在位置:Python中文网/ 问答频道 /正文

众所周知,元组不是由括号定义的,而是由逗号定义的Quote from documentation

A tuple consists of a number of values separated by commas

因此:

myVar1 = 'a', 'b', 'c'
type(myVar1)
# Result:
<type 'tuple'>

另一个显著的例子是:

myVar2 = ('a')
type(myVar2)
# Result:
<type 'str'>  

myVar3 = ('a',)
type(myVar3)
# Result:
<type 'tuple'>

即使是单元素元组也需要逗号,并且总是使用括号来避免混淆我的问题是:为什么不能在列表中省略数组的括号?例如:

myList1 = ['a', 'b']
myList2 = ['c', 'd']

print([(v1,v2) for v1 in myList1 for v2 in myList2])
# Works, result:
[('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd')]

print([v1,v2 for v1 in myList1 for v2 in myList2])
# Does not work, result:
SyntaxError: invalid syntax

第二个列表理解不就是下面这个循环的语法糖吗?这个循环确实有效

myTuples = []
for v1 in myList1:
    for v2 in myList2:
        myTuple = v1,v2
        myTuples.append(myTuple)
print myTuples
# Result:
[('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd')]

Tags: infor定义typeresultv2括号元组
3条回答

不存在引起此限制的解析器问题。与Silvio Mayolo的回答相反,LL(1)解析器可以很好地解析无括号语法。在原始列表理解补丁的早期版本中,括号是可选的;它们只是为了使含义更清楚而被强制执行

引用2000年Guido van Rossum的话,在一篇response中,有人担心[x, y for ...]会导致解析器问题

Don't worry. Greg Ewing had no problem expressing this in Python's own grammar, which is about as restricted as parsers come. (It's LL(1), which is equivalent to pure recursive descent with one lookahead token, i.e. no backtracking.)

Here's Greg's grammar:

atom: ... | '[' [testlist [list_iter]] ']' | ...
  list_iter: list_for | list_if
  list_for: 'for' exprlist 'in' testlist [list_iter]
  list_if: 'if' test [list_iter]

Note that before, the list syntax was '[' [testlist] ']'. Let me explain it in different terms:

The parser parses a series comma-separated expressions. Previously, it was expecting ']' as the sole possible token following this. After the change, 'for' is another possible following token. This is no problem at all for any parser that knows how to parse matching parentheses!

If you'd rather not support [x, y for ...] because it's ambiguous (to the human reader, not to the parser!), we can change the grammar to something like:

'[' test [',' testlist | list_iter] ']'

(Note that | binds less than concatenation, and [...] means an optional part.)

另请参见线程中的next response,Greg Ewing在其中运行

>>> seq = [1,2,3,4,5]
>>> [x, x*2 for x in seq]
[(1, 2), (2, 4), (3, 6), (4, 8), (5, 10)]

在列表理解补丁的早期版本上,它工作得很好

当我觉得有点太尖刻时,我想出了一个理由

它开始将表达式解析为list/set/tuple,并期望得到一个,而不是一个for标记

例如:

$ python3.6 test.py
  File "test.py", line 1
    [a, b for a, b in c]
            ^
SyntaxError: invalid syntax

标记如下:

$ python3.6 -m tokenize test.py
0,0-0,0:            ENCODING       'utf-8'        
1,0-1,1:            OP             '['            
1,1-1,2:            NAME           'a'            
1,2-1,3:            OP             ','            
1,4-1,5:            NAME           'b'            
1,6-1,9:            NAME           'for'          
1,10-1,11:          NAME           'a'            
1,11-1,12:          OP             ','            
1,13-1,14:          NAME           'b'            
1,15-1,17:          NAME           'in'           
1,18-1,19:          NAME           'c'            
1,19-1,20:          OP             ']'            
1,20-1,21:          NEWLINE        '\n'           
2,0-2,0:            ENDMARKER      ''     

Python的语法是LL(1),这意味着它在解析时只向前看一个符号

[(v1, v2) for v1 in myList1 for v2 in myList2]

在这里,解析器看到如下内容

[ # An opening bracket; must be some kind of list
[( # Okay, so a list containing some value in parentheses
[(v1
[(v1,
[(v1, v2
[(v1, v2)
[(v1, v2) for # Alright, list comprehension

然而,如果没有括号,它必须在早些时候作出决定

[v1, v2 for v1 in myList1 for v2 in myList2]

[ # List-ish thing
[v1 # List containing a value; alright
[v1, # List containing at least two values
[v1, v2 # Here's the second value
[v1, v2 for # Wait, what?

回溯的解析器往往非常慢,因此LL(1)解析器不会回溯。因此,不明确的语法是被禁止的

相关问题 更多 >

    热门问题