Le langage Python (en particulier 3.x) permet un déballage très général des itérables, dont un exemple simple est
a, *rest = 1, 2, 3
Au fil des ans, ce déballage s'est progressivement généralisé (voir par exemple PEP 3132 et PEP 448 ), ce qui lui permet d'être utilisé dans de plus en plus de circonstances. En tant que tel, j'ai été surpris de découvrir que la syntaxe suivante n'est pas valide dans Python 3.6 (et le reste dans Python 3.7):
def f():
rest = [2, 3]
return 1, *rest # Invalid
Je peux le faire fonctionner en encapsulant le Tuple retourné entre parenthèses comme ceci:
def f():
rest = [2, 3]
return (1, *rest) # Valid
Le fait que j'utilise ceci dans une instruction return
semble être important, car
t = 1, *rest
est en effet légal et se traduit par le même avec et sans parenthèses.
Ce cas a-t-il simplement été oublié par les développeurs Python, ou y a-t-il une raison pour laquelle ce cas n'est pas une syntaxe valide?
Cela rompt un contrat important que je pensais avoir avec le langage Python. Considérez la solution suivante (également valide):
def f():
rest = [2, 3]
t = 1, *rest
return t
Normalement, quand j'ai un code comme celui-ci, je considère que t
est un nom temporaire, dont je devrais pouvoir me débarrasser en remplaçant simplement t
dans la ligne de fond par sa définition. Dans ce cas cependant, cela conduit au code invalide
def f():
rest = [2, 3]
return 1, *rest
Bien sûr, ce n'est pas grave d'avoir à placer des parenthèses autour de la valeur de retour, mais généralement des parenthèses supplémentaires ne sont nécessaires que pour faire la distinction entre plusieurs résultats possibles (regroupement). Ici, ce n'est pas le cas, car la suppression des parenthèses ne produit pas d'autres comportements indésirables, mais plutôt aucun comportement du tout.
Je soupçonne que c'est un accident, basé sur les commentaires de ce commit pour Python 3.2.
Cette validation a permis à l'expression d'affectation de prendre un testlist_star_expr
production (ce qui permet le décompactage non entre parenthèses), mais a laissé l'instruction return en prenant une production testlist
. Je soupçonne que le commit vient de manquer cela (et peut-être d'autres endroits, mais je me concentre sur le return_stmt
production pour l'instant).
Je suis allé de l'avant et j'ai modifié le fichier Python Grammar/Grammar pour permettre cela. Tous les tests continuent de passer, y compris ceux du test_grammar.py
fichier (mais cela ne semble pas terriblement exhaustif).
Si vous êtes curieux, c'est le changement que j'ai fait . N'hésitez pas à cloner ou à télécharger ma fourchette .
MISE À JOUR: J'ai envoyé un problème bpo et un pull request pour le retour (et rendement) déballage.