Por que criar uma lista de tuplas usando compreensão de lista requer parênteses?

8

Conforme observado no HOWTO de Programação Funcional , para criar uma lista de tuplas usando compreensão de lista, parênteses devem ser usados. Particularmente, isso é expresso no documento na citação a seguir.

Para evitar a introdução de uma ambiguidade na gramática do Python, se a expressão estiver criando uma tupla, ela deverá estar entre parênteses.

Então, como exemplos:

[x, y for x in seq1 for y in seq2]  # This is a syntex error
[(x, y) for x in seq1 for y in seq2]  # This is a correct expression of list of tuples using list comprehension

Que ambiguidade é evitada ao forçar o uso de parênteses na expressão de uma lista de tuplas usando compreensão de lista?

Isaac To
fonte
1
@ Georgy: Infelizmente, a resposta atualmente aceita para essa pergunta está errada. (É o que eu imaginaria antes de encontrar a confirmação, caso contrário, mas ainda está errado.)
user2357112 apoia Monica em
Consulte também Por que as tuplas em uma compreensão de lista precisam de parênteses? , à qual a resposta incorreta se refere a @ user2357112.
John Kugelman 03/04

Respostas:

9

Depois de muita pesquisa na lista de e-mails, encontrei uma declaração bastante inequívoca de que o analisador estava bem com isso. Os parênteses foram tornados obrigatórios para tornar o significado mais claro. Aqui está uma citação de Guido em 2000 na lista de discussão python-dev:

Não se preocupe. Greg Ewing não teve nenhum problema em expressar isso na gramática do Python, que é tão restrita quanto os analisadores. (É LL (1), que é equivalente a uma descida recursiva pura com um token à procura de lookahead, ou seja, sem retorno.)

Aqui está a gramática de Greg:

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

Observe que antes, a sintaxe da lista era '[' [testlist] ']'. Deixe-me explicar em termos diferentes:

O analisador analisa uma série de expressões separadas por vírgula. Anteriormente, esperava ']'como o único sinal possível após isso. Após a alteração, 'for'é outro token possível a seguir. Isso não é problema para qualquer analisador que sabe analisar parênteses correspondentes!

Se você preferir não apoiar, [x, y for ...]porque é ambíguo (para o leitor humano, não para o analisador!), Podemos mudar a gramática para algo como:

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

(Observe que |liga menos que concatenação e [...]significa uma parte opcional.)

Veja também a próxima resposta no tópico, onde Greg Ewing é executado

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

em uma versão anterior do patch de compreensão da lista e funciona muito bem.

user2357112 suporta Monica
fonte
-1

Dos documentos :

Como você vê, as tuplas de saída são sempre colocadas entre parênteses, para que as tuplas aninhadas sejam interpretadas corretamente; eles podem ser inseridos com ou sem parênteses, embora frequentemente parênteses sejam necessários (se a tupla fizer parte de uma expressão maior). Não é possível atribuir aos itens individuais de uma tupla, no entanto, é possível criar tuplas que contêm objetos mutáveis, como listas.

Dentro de uma lista, as tuplas de compreensão são aninhadas dentro de uma lista. Portanto, eles devem estar entre parênteses. Mas quando não estão sendo aninhados, por exemplo, the_tuples = 'a','b','c'eles não são necessários porque são automaticamente reconhecidos como tuplas.

Wasif Hasan
fonte
-2

O Python possui vários elementos sintáticos com parênteses opcionais. Nesse caso, são eles:

  • tuple literal x, y
  • expressão gerador y for x in seq1 for y in seq2

Em casos inequívocos, eles podem ser usados sem parênteses adicionais:

  • b = x, y
  • sum(y for x in seq1 for y in seq2)

No entanto, o uso de ambos na mesma expressão é ambíguo. Parênteses são necessários para esclarecer o significado:

  • [(x, y) for x in seq1 for y in seq2]
  • [x, (y for x in seq1 for y in seq2)]

De acordo com a gramática Python3, lista apresenta [...]são definidos como contendo quer uma lista de expressão ( a, b, *c, d) ou uma compreensão ( a for a in b).

MisterMiyagi
fonte
1
As expressões de gerador não existiam no momento em que essa sintaxe foi introduzida.
user2357112 suporta Monica
@ user2357112supportsMonica Isso não altera a ambiguidade existente hoje.
MisterMiyagi