28 votes

Sémantique du déballage de tuple en python

Pourquoi python autorise-t-il uniquement les arguments nommés à suivre une expression de décompression de tuple dans un appel de fonction?

 >>> def f(a,b,c):
...     print a, b, c
... 
>>> f(*(1,2),3)
  File "<stdin>", line 1
SyntaxError: only named arguments may follow *expression
 

S'agit-il simplement d'un choix esthétique, ou y a-t-il des cas où autoriser cela conduirait à des ambiguïtés?

29voto

andrew cooke Points 20902

je suis assez sûr que la raison pour laquelle les gens "naturellement" je n'aime pas c'est parce que c'est le sens de la plus tard arguments ambigu, en fonction de la longueur de l'interpolation de la série:

def dangerbaby(a, b, *c):
    hug(a)
    kill(b) 

>>> dangerbaby('puppy', 'bug')
killed bug
>>> cuddles = ['puppy']
>>> dangerbaby(*cuddles, 'bug')
killed bug
>>> cuddles.append('kitten')
>>> dangerbaby(*cuddles, 'bug')
killed kitten

vous ne pouvez pas dire simplement en regardant les deux derniers appels d' dangerbaby qui fonctionne comme prévu et que l'on tue à petit chaton fluffykins.

bien sûr, une partie de cette incertitude est également présent lors de l'interpolation à la fin. mais la confusion est contraint à l'interpolation de la séquence, cela n'affecte pas d'autres arguments, comme bug.

[j'ai fait une recherche rapide pour voir si je pouvais trouver quoi que ce soit officiel. il semble que l' * préfixe pour varags a été introduit en python 0.9.8. la syntaxe précédente est discuté ici, et les règles de fonctionnement ont été plutôt complexe. depuis l'ajout des arguments supplémentaires "devait" passer à la fin quand il n'y a pas de * marqueur, il semble que tout simplement reporté. enfin il y a une mention ici d'une longue discussion sur les listes d'arguments qui n'a pas été par e-mail.]

6voto

alexis Points 10856

Je soupçonne que c'est pour des raisons de cohérence avec les étoiles de notation en fonction des définitions, qui est, après tout, le modèle de l'étoile de la notation dans les appels de fonction.

Dans la définition suivante, le paramètre *c sera slurp tous les non-mot-clé arguments, alors, évidemment, lorsqu' f est appelé, le seul moyen de transmettre une valeur de d sera comme un argument mot-clé.

def f(a, b, *c, d=1):
    print "slurped", len(c)

(Par exemple "mot-clé-seuls les paramètres" sont uniquement pris en charge en Python 3. En Python 2, il n'y est aucun moyen pour affecter des valeurs après un étoilé argument ci-dessus est illégal.)

Ainsi, dans une fonction de définition de la vedette argument doit suivre tous les ordinaires des arguments de position. Ce que vous avez observé, c'est que la même règle a été étendue à des appels de fonction. De cette façon, la star de la syntaxe est la même pour les déclarations de fonction et des appels de fonction.

Un autre parallélisme, c'est que vous ne pouvez avoir qu'un (seul)étoilé argument dans l'appel de la fonction. La suite est illégal, si l'on peut facilement imaginer qu'il soit autorisé.

f(*(1,2), *(3,4))

1voto

wberry Points 6068

Tout d'abord, il est simple de fournir une interface très similaire vous-même à l'aide d'une fonction wrapper:

def applylast(func, arglist, *literalargs):
  return func(*(literalargs + arglist))

applylast(f, (1, 2), 3)  # equivalent to f(3, 1, 2)

Deuxièmement, l'amélioration de l'interprète à l'appui de votre syntaxe nativement peut ajouter des frais généraux pour le très critiques des performances de l'activité de la fonction de demande. Même si elle ne nécessite que quelques instructions supplémentaires dans le code compilé, en raison de la forte utilisation de ces routines, qui pourrait être inacceptable pour la performance de peine en échange d'une fonctionnalité qui n'est pas appelée pour toutes qui souvent et facilement réalisable dans une bibliothèque utilisateur.

1voto

Simeon Visser Points 30697

Quelques observations:

  1. Python processus arguments de position avant les arguments mots-clefs (f(c=3, *(1, 2)) dans votre exemple encore imprime 1 2 3). Ceci n'a de sens que (i) la plupart des arguments dans les appels de fonction sont positionnels et (ii) la sémantique d'un langage de programmation doivent être sans ambiguïté (c'est à dire, un choix doit être fait sur l'ordre dans lequel les processus de positionnement de mots clés et de ses arguments).
  2. Si nous devions avoir une position argument de la droite dans un appel de fonction, il serait difficile de définir ce que cela signifie. Si nous appelons f(*(1, 2), 3), qui devrait être f(1, 2, 3) ou f(3, 1, 2) et pourquoi ces choix ont plus de sens que les autres?
  3. Pour une explication officielle, PEP 3102 fournit beaucoup de perspicacité sur la façon dont les définitions de fonctions de travail. L'étoile (*) dans une fonction de définition indique la fin de la position des arguments (section Spécifications). Pour comprendre pourquoi, considérez: def g(a, b, *c, d). Il n'y a aucun moyen de fournir une valeur pour l' d autrement que comme un argument mot-clé (position, les arguments de la être "attrapé" par c).
  4. Il est important de réaliser ce que cela signifie: la star, marque la fin d'arguments de position, cela signifie que tous les arguments de position doit être dans cette position ou à gauche de celle-ci.

0voto

Ashwini Chaudhary Points 94431

changer l'ordre:

 def f(c,a,b):
    print(a,b,c)
f(3,*(1,2))
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X