web-dev-qa-db-fra.com

Pourquoi ne puis-je pas utiliser une expression étoilée?

Mon code 

$ python
Python 3.5.2 |Continuum Analytics, Inc.| (default, Jul  2 2016, 17:53:06) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = (1, 2)
>>> '%d %d %d' % (0, *a)
'0 1 2'
>>> '%d %d %d' % (*a, 3)
'1 2 3'
>>> '%d %d' % (*a)
  File "<stdin>", line 1
SyntaxError: can't use starred expression here
>>> 

Ma question, pourquoi?

Sur un ton plus sérieux: je voudrais une réponse, ou une référence, qui détaille tous les tenants et aboutissants de l'utilisation d'une expression étoilée, car il arrive que je sois parfois surpris de son comportement.

Addenda

Pour refléter certains des commentaires éclairants que A immédiatement suivi ma question, j’ajoute le code suivant

>>> '%d %d' % (, *a)
  File "<stdin>", line 1
    '%d %d' % (, *a)
               ^
SyntaxError: invalid syntax
>>> '%d %d' % (*a,)
'1 2'
>>> 

(J'avais essayé la partie (, a) avant de poster la question initiale mais je l'ai omise car l'erreur n'était pas liée à la vedette.)

Il existe une syntaxe, en python ≥ 3.5, qui "fonctionne", mais j'aimerais néanmoins un peu de compréhension.

17
gboffi

C'est parce que ça:

(a)

Est-ce juste une valeur entourée de parenthèses. Ce n'est pas un nouvel objet Tuple. Alors ton expression:

>>> '%d %d' % (*a)

sera traduit en:

>>> '%d %d' % * a

ce qui est évidemment faux en termes de syntaxe python.

Afin de créer un nouveau tuple, avec une expression en tant qu'initialiseur, vous devez ajouter un ',' après celle-ci:

>>> '%d %d' % (*a,)

Remarque: à moins que a soit un générateur, vous pouvez simplement taper:

>>> '%d %d' % a

Aussi, si je peux suggérer quelque chose: vous pouvez commencer à utiliser des expressions de formatage de nouveau style. Ils sont grands!

>>> "{} {}".format(*a)

Vous pouvez en savoir plus à leur sujet dans ces t w o paragraphes de la documentation python, il y a aussi this great website. La ligne ci-dessus utilise le mécanisme de décompression des arguments décrit ci-dessous.

Expressions étoilées

Il existe de nombreuses autres utilisations d’expressions marquées que la création d’une nouvelle liste/tuple/dictionnaire. La plupart d'entre eux sont décrits dans ce PEP , et celui-ci

Tous se résument à deux types:

RValue déballage:

>>> a, *b, c = range(5)
# a = 0
# b = [1, 2, 3]
# c = 4
>>> 10, *range(2)
(10, 0, 1)

Initialisation d'un objet/dictionnaire Iterable (notez que vous pouvez aussi décompresser les dictionnaires dans des listes!):

>>> [1, 2, *[3, 4], *[5], *(6, 7)]
[1, 2, 3, 4, 5, 6, 7]
>>> (1, *[2, 3], *{"a": 1})
(1, 2, 3, 'a')
>>> {"a": 1, **{"b": 2, "c": 3}, **{"c": "new 3", "d": 4}}
{'a': 1, 'b': 2, 'c': 'new 3', 'd': 4}

Bien entendu, l’utilisation la plus fréquente est la décompression des arguments:

positional_arguments = [12, "a string", (1, 2, 3), other_object]
keyword_arguments = {"hostname": "localhost", "port": 8080}
send(*positional_arguments, **keyword_arguments)

ce qui se traduirait par ceci:

send(12, "a string", (1, 2, 3), other_object, hostname="localhost", port=8080)

Ce sujet a déjà été traité en grande partie dans un autre Stack Overflow question .

22
Błażej Michalik

Ma question, pourquoi?

Parce que votre syntaxe python ne le permet pas. C'est défini comme ça, donc il n'y a pas de vrai "pourquoi".

aussi, c'est inutile. 

"%d %d" % a

travaillerait.

Donc, vous devez convertir votre expansion en un tuple - et la bonne façon de le faire serait, comme l'a souligné Lafexlos, d'être 

"%d %d" % (*a,)
3
Marcus Müller

C'est parce que:

>>> '%d %d' % (*a)

Peut être juste:

>>> '%d %d' %a

Bien sûr alors capable de faire:

>>> '%d %d' % (*a,)

Mais alors:

>>> (*a,)==a
True
>>> 

Ou tu peux faire:

>>> '%d %d' % [*a]

Mais alors:

>>> [*a]
[1, 2]
>>> a
(1, 2)
>>> 

Alors:

>>> Tuple([*a])==a
True
0
U9-Forward