3 votes

Utilisation spéciale des args / kwargs

J'ai besoin de faire quelque chose comme ça :

def func1(a, *args, b="BBB", **kwargs):
    print "a=%s b=%s args=%s kwargs=%s" % (a, b, args, kwargs)

Donc ça appelle comme ça :

func1("AAAA", h="HHH", j="JJJ")

Produit la sortie :

a=AAAA b=BBB args=() kwargs={'h': 'HHH', 'j': 'JJJ'}

Mais il n'est pas possible de mettre un argument nommé par défaut après *args . ( SyntaxError: invalid syntax )

  • Pourquoi cela n'est-il pas autorisé ?
  • Existe-t-il un moyen lisible de mettre en œuvre ce système ? Le seul moyen que je connaisse est b=kwargs.pop("b", "BBB") mais ce n'est pas très lisible. Je préférerais que ce soit dans la définition de l'appel de fonction, là où il faut : c'est un paramètre qui va toujours ont une valeur, soit une valeur par défaut, soit une valeur donnée par l'utilisateur.

EDITAR

Je pourrais mettre b devant args :

def func1(a, b="BBB", *args, **kwargs):
    print "a=%s b=%s args=%s kwargs=%s" % (a, b, args, kwargs)

Mais cela voudrait dire que cet appel :

func1("AAAA", "CCC", h="HHH", j="JJJ")

Assigne "CCC" à b ce que je ne veux pas. Je veux b pour être une arg nommée, et non pas une arg possitionnelle.

2voto

ecatmur Points 64173

C'est parfaitement valable dans Python 3 ( démonstration ) ; PEP 3102 introduit arguments par mot-clé uniquement .

Dans Python 2.x, vous devrez continuer à utiliser kwargs.pop ou un décorateur approprié :

1voto

EOL Points 24342

En Python 2 ,

Le paradigme actuel d'appel de fonctions Python permet de spécifier les arguments spécifiés soit par position, soit par mot-clé. Un argument peut être renseigné soit explicitement par son nom, soit implicitement par sa position.

En conséquence def func1(a, *args, b="BBB", **kwargs) serait ambiguë et n'est donc pas autorisée : dans un appel func1(1, 2) devrait args == () y b == 2 ou args = (2,) y b == "BBB" ?

C'est pourquoi def func1(a, b="BBB", *args, **kwargs) est, en revanche, acceptée (même si elle ne fait pas ce que vous voulez) : b est toujours passé comme deuxième argument, même dans un appel comme func1(1, c=3, b=2) (il est équivalent à func1(1, 2, c=3) ).

Comme ecatmur l'a noté, Python 3 a modifié la façon dont les arguments sont traités, ce qui apporte la flexibilité dont vous avez besoin.

0voto

glglgl Points 35668
def func1(a, *args, **kwargs):
    b, k = (lambda b="BBBB", **k: b, k)(**kwargs)
    print "a=%s b=%s args=%s kwargs=%s" % (a, b, args, k)

pourrait être une alternative.

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