277 votes

Que signifient *args et **kwargs ?

Que font exactement *args y **kwargs C'est-à-dire ?

D'après la documentation de Python, il semble qu'il passe dans un tuple d'arguments.

def foo(hello, *args):
    print hello

    for each in args:
        print each

if __name__ == '__main__':
    foo("LOVE", ["lol", "lololol"])

Cela s'imprime :

LOVE
['lol', 'lololol']

Comment les utiliser efficacement ?

17 votes

Juste un mauvais jeu de mots sur les heures et les kilo-Watt-heures.

6 votes

Cet article peut être très utile pour comprendre en profondeur le thème : agiliq.com/blog/2012/06/comprendre-args-et-kwargs

262voto

Paul D. Waite Points 35456

Mettez *args et/ou **kwargs comme derniers éléments de la liste d'arguments de votre définition de fonction permet à cette fonction d'accepter un nombre arbitraire d'arguments et/ou de mots-clés.

Par exemple, si vous voulez écrire une fonction qui renvoie la somme de tous ses arguments, quel que soit le nombre que vous fournissez, vous pouvez l'écrire comme suit :

def my_sum(*args):
    return sum(args)

Elle est probablement plus couramment utilisée dans la programmation orientée objet, lorsque vous remplacez une fonction et que vous souhaitez appeler la fonction originale avec les arguments que l'utilisateur lui fournit.

Vous n'avez pas besoin de les appeler args y kwargs c'est juste une convention. C'est le * y ** qui font la magie.

La documentation officielle de Python contient un regard plus approfondi .

5 votes

Pas de problème, vous êtes le bienvenu. J'ai aussi été perturbé pendant un certain temps. Si vous vous lancez sérieusement dans Python, je vous recommande chaudement " Programming Python " de Mark Lutz.

43 votes

Peut-être un lien vers le tutoriel qui explique cela en profondeur, et qui devrait être lu par tout le monde : docs.python.org/tutorial/

1 votes

@AliAfshar : Votre lien était tout ce dont j'avais besoin, il aurait dû être la réponse par lui-même. Merci !

93voto

S.Lott Points 207588

Nous les utilisons également pour gérer les héritages.

class Super( object ):
   def __init__( self, this, that ):
       self.this = this
       self.that = that

class Sub( Super ):
   def __init__( self, myStuff, *args, **kw ):
       super( Sub, self ).__init__( *args, **kw )
       self.myStuff= myStuff

x= Super( 2.7, 3.1 )
y= Sub( "green", 7, 6 )

De cette façon, Sub ne sait pas vraiment (ou ne se soucie pas) de l'initialisation de la superclasse. Si vous vous rendez compte que vous devez modifier la superclasse, vous pouvez corriger les choses sans avoir à vous soucier des détails dans chaque sous-classe.

6 votes

C'est l'une des réponses les plus utiles que j'ai trouvées sur la manière d'utiliser super . Cette réponse date d'il y a plus de 5 ans, mais je pense que c'est toujours une bonne façon d'utiliser les super dans Python 2.X, correct ?

0 votes

Oui, toujours la façon de faire.

0 votes

Merci, mais ce serait bien si vous pouviez fournir un exemple réel, pourquoi et quand l'utiliser. Dans l'exemple ci-dessus, que se passe-t-il si je ne le fais pas ?

69voto

orip Points 28225

Remarquez le truc cool dans Commentaire de S.Lott - vous pouvez également appeler des fonctions avec *mylist y **mydict pour décompresser les arguments positionnels et les mots-clés :

def foo(a, b, c, d):
  print a, b, c, d

l = [0, 1]
d = {"d":3, "c":2}

foo(*l, **d)

Sera imprimé : 0 1 2 3

0 votes

Vous pouvez aussi faire *mydict (pas **mylist ), mais le résultat sera légèrement différent (et inattendu pour certains).

2 votes

Simple, concis, et un exemple facile à suivre pour illustrer le propos. Mon type de réponse préféré !

0 votes

@Tadeck Vous pouvez faire *x pour tout itérable et **y pour tout type de cartographie. Puisqu'un dict est à la fois un itérable et un mapping, vous pouvez faire les deux. Voir aussi stackoverflow.com/questions/8601268/

25voto

orip Points 28225

Une autre bonne utilisation de *args y **kwargs La fonction "catch all" : vous pouvez définir des fonctions génériques "catch all", ce qui est idéal pour les décorateurs où vous retournez un tel wrapper au lieu de la fonction originale.

Un exemple avec un décorateur de mise en cache trivial :

import pickle, functools
def cache(f):
  _cache = {}
  def wrapper(*args, **kwargs):
    key = pickle.dumps((args, kwargs))
    if key not in _cache:
      _cache[key] = f(*args, **kwargs) # call the wrapped function, save in cache
    return _cache[key] # read value from cache
  functools.update_wrapper(wrapper, f) # update wrapper's metadata
  return wrapper

import time
@cache
def foo(n):
  time.sleep(2)
  return n*2

foo(10) # first call with parameter 10, sleeps
foo(10) # returns immediately

18voto

Kaushik Ghose Points 267

Juste pour clarifier comment déballer les arguments, et prendre soin des arguments manquants, etc.

def func(**keyword_args):
  #-->keyword_args is a dictionary
  print 'func:'
  print keyword_args
  if keyword_args.has_key('b'): print keyword_args['b']
  if keyword_args.has_key('c'): print keyword_args['c']

def func2(*positional_args):
  #-->positional_args is a tuple
  print 'func2:'
  print positional_args
  if len(positional_args) > 1:
    print positional_args[1]

def func3(*positional_args, **keyword_args):
  #It is an error to switch the order ie. def func3(**keyword_args, *positional_args):
  print 'func3:'
  print positional_args
  print keyword_args

func(a='apple',b='banana')
func(c='candle')
func2('apple','banana')#It is an error to do func2(a='apple',b='banana')
func3('apple','banana',a='apple',b='banana')
func3('apple',b='banana')#It is an error to do func3(b='banana','apple')

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