Que font ** (double étoile/astérisque) et * (étoile/astérisque) pour les paramètres?

dans les définitions de méthode suivantes, Que font les * et ** pour param2 ?

def foo(param1, *param2):
def bar(param1, **param2):
1646
demandé sur Florian_1990 2008-08-31 19:04:35

18 réponses

le *args et **kwargs est un langage courant pour permettre un nombre arbitraire d'arguments aux fonctions comme décrit dans la section plus sur la définition des fonctions dans la documentation Python.

le *args vous donnera tous les paramètres de fonction comme un tuple :

In [1]: def foo(*args):
   ...:     for a in args:
   ...:         print a
   ...:         
   ...:         

In [2]: foo(1)
1


In [4]: foo(1,2,3)
1
2
3

le **kwargs vous donnera tout mots-clés arguments sauf pour ceux correspondant à un paramètre formel comme un dictionnaire.

In [5]: def bar(**kwargs):
   ...:     for a in kwargs:
   ...:         print a, kwargs[a]
   ...:         
   ...:         

In [6]: bar(name='one', age=27)
age 27
name one

les deux idiomes peuvent être mélangés avec des arguments normaux pour permettre un ensemble d'arguments fixes et quelques variables:

def foo(kind, *args, **kwargs):
   pass

un autre usage de l'idiome *l est de despack argument lists lors de l'appel d'une fonction.

In [9]: def foo(bar, lee):
   ...:     print bar, lee
   ...:     
   ...:     

In [10]: l = [1,2]

In [11]: foo(*l)
1 2

En Python 3, il est possible d'utiliser *l sur le côté gauche d'une affectation ( déballage itératif étendu ), bien qu'il donne une liste au lieu d'un tuple dans ce contexte:

first, *rest = [1,2,3,4]
first, *l, last = [1,2,3,4]

aussi Python 3 ajoute nouvelle sémantique (se référer PEP 3102 ):

def func(arg1, arg2, arg3, *, kwarg1, kwarg2):
    pass

une telle fonction n'accepte que 3 arguments de position, et tout ce qui suit * ne peut être passé qu'en tant qu'arguments de mots clés.

1618
répondu Peter Hoffmann 2017-05-28 12:54:20

Il est également intéressant de noter que vous pouvez utiliser * et ** lors de l'appel de fonctions. C'est un raccourci qui vous permet de passer plusieurs arguments à une fonction directement en utilisant une liste/tuple ou un dictionnaire. Par exemple, si vous avez la fonction suivante:

def foo(x,y,z):
    print("x=" + str(x))
    print("y=" + str(y))
    print("z=" + str(z))

vous pouvez faire des choses comme:

>>> mylist = [1,2,3]
>>> foo(*mylist)
x=1
y=2
z=3

>>> mydict = {'x':1,'y':2,'z':3}
>>> foo(**mydict)
x=1
y=2
z=3

>>> mytuple = (1, 2, 3)
>>> foo(*mytuple)
x=1
y=2
z=3

Remarque: Les touches mydict être nommé exactement comme les paramètres de la fonction foo . Sinon il lancera un TypeError :

>>> mydict = {'x':1,'y':2,'z':3,'badnews':9}
>>> foo(**mydict)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() got an unexpected keyword argument 'badnews'
468
répondu Lorin Hochstein 2018-03-07 01:53:17

le simple * signifie qu'il peut y avoir n'importe quel nombre d'arguments de position supplémentaires. foo() peut être invoqué comme foo(1,2,3,4,5) . Dans le corps de foo () param2 est une séquence contenant 2-5.

le double ** signifie qu'il peut y avoir n'importe quel nombre de paramètres nommés supplémentaires. bar() peut être invoqué comme bar(1, a=2, b=3) . Dans le corps de bar() param2 est un dictionnaire contenant {'a':2, 'b':3 }

avec le code suivant:

def foo(param1, *param2):
    print param1
    print param2

def bar(param1, **param2):
    print param1
    print param2

foo(1,2,3,4,5)
bar(1,a=2,b=3)

la sortie est

1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}
135
répondu nickd 2008-08-31 15:20:21

Quoi ** (étoile double) et * (l'étoile) à faire pour les paramètres

ils permettent aux fonctions d'être défini pour accepter et pour utilisateurs de passer n'importe quel nombre d'arguments, de position ( * ) et de mot-clé ( ** ).

Définition Des Fonctions

*args permet un nombre quelconque d'options arguments de position (paramètres), qui seront assignés à un tuple nommé args .

**kwargs permet pour n'importe quel nombre d'arguments (paramètres) de mot-clé optionnel, qui sera dans un dict nommé kwargs .

vous pouvez (et devriez) choisir n'importe quel nom approprié, mais si l'intention est que les arguments soient de sémantique non-spécifique, args et kwargs sont des noms standard.

Expansion, Passer un certain nombre d'arguments

vous pouvez également utiliser *args et **kwargs pour passer dans les paramètres des listes (ou n'importe quel itérable) et dicts (ou n'importe quel mapping), respectivement.

la fonction recevant les paramètres n'a pas besoin de savoir qu'ils sont élargis.

par exemple, xrange de Python 2 n'attend pas explicitement *args , mais puisqu'il prend 3 entiers comme arguments:

>>> x = xrange(3) # create our *args - an iterable of 3 integers
>>> xrange(*x)    # expand here
xrange(0, 2, 2)

comme autre exemple, nous pouvons utiliser l'expansion de dict dans str.format :

>>> foo = 'FOO'
>>> bar = 'BAR'
>>> 'this is foo, {foo} and bar, {bar}'.format(**locals())
'this is foo, FOO and bar, BAR'

nouveau en Python 3: définition de fonctions avec des arguments mot-clé seulement

vous pouvez avoir arguments mot-clé seulement après le *args - par exemple, ici, kwarg2 doit être donné comme un argument mot-clé - pas positionnellement:

def foo(arg, kwarg=None, *args, kwarg2=None, **kwargs): 
    return arg, kwarg, args, kwarg2, kwargs

Utilisation:

>>> foo(1,2,3,4,5,kwarg2='kwarg2', bar='bar', baz='baz')
(1, 2, (3, 4, 5), 'kwarg2', {'bar': 'bar', 'baz': 'baz'})

aussi, * peut être utilisé par lui-même pour indiquer que le mot-clé seulement les arguments suivent, sans permettre des arguments de position illimités.

def foo(arg, kwarg=None, *, kwarg2=None, **kwargs): 
    return arg, kwarg, kwarg2, kwargs

ici, kwarg2 encore une fois doit être un argument de mot-clé explicitement nommé:

>>> foo(1,2,kwarg2='kwarg2', foo='foo', bar='bar')
(1, 2, 'kwarg2', {'foo': 'foo', 'bar': 'bar'})

et nous ne pouvons plus accepter les arguments de position illimités parce que nous n'avons pas *args* :

>>> foo(1,2,3,4,5, kwarg2='kwarg2', foo='foo', bar='bar')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: foo() takes from 1 to 2 positional arguments 
    but 5 positional arguments (and 1 keyword-only argument) were given

encore une fois, plus simplement, nous avons besoin kwarg à donner par nom, et non positionnellement:

def bar(*, kwarg=None): 
    return kwarg

dans cet exemple, nous voyons que si nous essayons de passer kwarg positionnellement, nous obtenons une erreur:

>>> bar('kwarg')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: bar() takes 0 positional arguments but 1 was given

nous devons explicitement passer le paramètre kwarg comme un argument de mot-clé.

>>> bar(kwarg='kwarg')
'kwarg'

Python 2 compatible demos

*args (typiquement dit" star-args") et **kwargs (les étoiles peuvent être impliquées par dire "kwargs", mais être explicite avec" double étoile kwargs") sont des idiomes courants de Python pour utiliser la notation * et ** . Ces noms de variables spécifiques ne sont pas nécessaires (par exemple, vous pouvez utiliser *foos et **bars ), mais une dérogation à la convention est susceptible d'enrager vos codeurs Python.

généralement, Nous utilisons lorsque nous ne savons pas ce que notre fonction va recevoir ou combien d'arguments on peut passer, et parfois même en nommant chaque variable séparément serait très confus et redondant (mais c'est un cas où généralement explicite est mieux qu'implicite).

exemple 1

la fonction suivante décrit comment ils peuvent être utilisés, et démontre le comportement. Remarque le nom b argument sera consommée par la deuxième position argument avant :

def foo(a, b=10, *args, **kwargs):
    '''
    this function takes required argument a, not required keyword argument b
    and any number of unknown positional arguments and keyword arguments after
    '''
    print('a is a required argument, and its value is {0}'.format(a))
    print('b not required, its default value is 10, actual value: {0}'.format(b))
    # we can inspect the unknown arguments we were passed:
    #  - args:
    print('args is of type {0} and length {1}'.format(type(args), len(args)))
    for arg in args:
        print('unknown arg: {0}'.format(arg))
    #  - kwargs:
    print('kwargs is of type {0} and length {1}'.format(type(kwargs),
                                                        len(kwargs)))
    for kw, arg in kwargs.items():
        print('unknown kwarg - kw: {0}, arg: {1}'.format(kw, arg))
    # But we don't have to know anything about them 
    # to pass them to other functions.
    print('Args or kwargs can be passed without knowing what they are.')
    # max can take two or more positional args: max(a, b, c...)
    print('e.g. max(a, b, *args) \n{0}'.format(
      max(a, b, *args))) 
    kweg = 'dict({0})'.format( # named args same as unknown kwargs
      ', '.join('{k}={v}'.format(k=k, v=v) 
                             for k, v in sorted(kwargs.items())))
    print('e.g. dict(**kwargs) (same as {kweg}) returns: \n{0}'.format(
      dict(**kwargs), kweg=kweg))

nous pouvons vérifier l'aide en ligne pour la signature de la fonction, avec help(foo) , qui nous dit

foo(a, b=10, *args, **kwargs)

appelons cette fonction avec foo(1, 2, 3, 4, e=5, f=6, g=7)

qui imprime:

a is a required argument, and its value is 1
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 2
unknown arg: 3
unknown arg: 4
kwargs is of type <type 'dict'> and length 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: g, arg: 7
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
4
e.g. dict(**kwargs) (same as dict(e=5, f=6, g=7)) returns: 
{'e': 5, 'g': 7, 'f': 6}

exemple 2

nous pouvons également l'appeler en utilisant une autre fonction, dans laquelle nous venons de fournir a :

def bar(a):
    b, c, d, e, f = 2, 3, 4, 5, 6
    # dumping every local variable into foo as a keyword argument 
    # by expanding the locals dict:
    foo(**locals()) 

bar(100) gravures:

a is a required argument, and its value is 100
b not required, its default value is 10, actual value: 2
args is of type <type 'tuple'> and length 0
kwargs is of type <type 'dict'> and length 4
unknown kwarg - kw: c, arg: 3
unknown kwarg - kw: e, arg: 5
unknown kwarg - kw: d, arg: 4
unknown kwarg - kw: f, arg: 6
Args or kwargs can be passed without knowing what they are.
e.g. max(a, b, *args) 
100
e.g. dict(**kwargs) (same as dict(c=3, d=4, e=5, f=6)) returns: 
{'c': 3, 'e': 5, 'd': 4, 'f': 6}

exemple 3: usage pratique dans les décorateurs

OK, donc peut-être que nous ne voyons pas encore l'utilité. Alors imaginez que vous ayez plusieurs fonctions avec du code redondant avant et/ou après le code de différenciation. Les fonctions nommées ci-dessous ne sont que du pseudo-code à titre indicatif.

def foo(a, b, c, d=0, e=100):
    # imagine this is much more code than a simple function call
    preprocess() 
    differentiating_process_foo(a,b,c,d,e)
    # imagine this is much more code than a simple function call
    postprocess()

def bar(a, b, c=None, d=0, e=100, f=None):
    preprocess()
    differentiating_process_bar(a,b,c,d,e,f)
    postprocess()

def baz(a, b, c, d, e, f):
    ... and so on

nous pourrions être en mesure de gérer cela différemment, mais nous pouvons certainement extraire la redondance avec un décorateur, et donc notre exemple ci-dessous montre comment *args et **kwargs peuvent être très utiles:

def decorator(function):
    '''function to wrap other functions with a pre- and postprocess'''
    @functools.wraps(function) # applies module, name, and docstring to wrapper
    def wrapper(*args, **kwargs):
        # again, imagine this is complicated, but we only write it once!
        preprocess()
        function(*args, **kwargs)
        postprocess()
    return wrapper

et maintenant chaque fonction enveloppée peut être écrite beaucoup plus succinctement, comme nous avons supprimé la redondance:

@decorator
def foo(a, b, c, d=0, e=100):
    differentiating_process_foo(a,b,c,d,e)

@decorator
def bar(a, b, c=None, d=0, e=100, f=None):
    differentiating_process_bar(a,b,c,d,e,f)

@decorator
def baz(a, b, c=None, d=0, e=100, f=None, g=None):
    differentiating_process_baz(a,b,c,d,e,f, g)

@decorator
def quux(a, b, c=None, d=0, e=100, f=None, g=None, h=None):
    differentiating_process_quux(a,b,c,d,e,f,g,h)

et en factorisant notre code, que *args et **kwargs nous permet de faire, nous réduisons les lignes de code, améliorer la lisibilité et la maintenabilité, et ont des emplacements canoniques uniques pour la logique dans notre programme. Si nous avons besoin de modifier une partie de cette structure, nous avons une place pour chaque changement.

112
répondu Aaron Hall 2016-12-20 20:21:05

commençons par comprendre ce que sont les arguments de position et les arguments de mots clés. Voici un exemple de définition de fonction avec des arguments de position .

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(1,2,3)
#output:
1
2
3

il s'agit donc d'une définition de fonction avec des arguments de position. Vous pouvez l'appeler avec des mots-clés/arguments nommés aussi bien:

def test(a,b,c):
     print(a)
     print(b)
     print(c)

test(a=1,b=2,c=3)
#output:
1
2
3

maintenant, étudions un exemple de définition de fonction avec mots clés arguments :

def test(a=0,b=0,c=0):
     print(a)
     print(b)
     print(c)
     print('-------------------------')

test(a=1,b=2,c=3)
#output :
1
2
3
-------------------------

vous pouvez aussi appeler cette fonction avec des arguments de position:

def test(a=0,b=0,c=0):
    print(a)
    print(b)
    print(c)
    print('-------------------------')

test(1,2,3)
# output :
1
2
3
---------------------------------

ainsi nous connaissons maintenant des définitions de fonction avec des arguments de position aussi bien que des mots-clés.

étudions maintenant l'opérateur ' * 'et'**'.

veuillez noter que ces opérateurs peuvent être utilisés dans 2 zones:

a) appel de fonction

b) définition de la fonction

L'utilisation de '*' et '**' opérateur appel de fonction.

allons droit à un exemple et discutons-en.

def sum(a,b):  #receive args from function calls as sum(1,2) or sum(a=1,b=2)
    print(a+b)

my_tuple = (1,2)
my_list = [1,2]
my_dict = {'a':1,'b':2}

# Let us unpack data structure of list or tuple or dict into arguments with help of '*' operator
sum(*my_tuple)   # becomes same as sum(1,2) after unpacking my_tuple with '*'
sum(*my_list)    # becomes same as sum(1,2) after unpacking my_list with  '*'
sum(**my_dict)   # becomes same as sum(a=1,b=2) after unpacking by '**' 

# output is 3 in all three calls to sum function.

, Donc n'oubliez pas

lorsque l'opérateur " * " ou "* * "est utilisé dans un appel de fonction 151990920" -

'*' opérateur déballe structure de données telle qu'une liste ou tuple dans les arguments nécessaires par la définition de la fonction.

'**' opérateur décompresse un dictionnaire dans les arguments requis par la définition de la fonction.

étudions maintenant l'utilisation de l'opérateur " * "dans définition de la fonction . Exemple:

def sum(*args): #pack the received positional args into data structure of tuple. after applying '*' - def sum((1,2,3,4))
    sum = 0
    for a in args:
        sum+=a
    print(sum)

sum(1,2,3,4)  #positional args sent to function sum
#output:
10

Dans la fonction définition ' * ' opérateur de paquets reçus des arguments dans un tuple.

voyons maintenant un exemple de '**' utilisé dans la définition de la fonction:

def sum(**args): #pack keyword args into datastructure of dict after applying '**' - def sum({a:1,b:2,c:3,d:4})
    sum=0
    for k,v in args.items():
        sum+=v
    print(sum)

sum(a=1,b=2,c=3,d=4) #positional args sent to function sum

Dans la fonction définition Les '**' opérateur de paquets reçus des arguments dans un dictionnaire.

Donc n'oubliez pas:

Dans un appel de fonction ' * ' déballe la structure de données de tuple ou une liste en position ou un mot-clé arguments à être reçu par la définition de la fonction.

dans un appel de fonction les '**' déballe la structure de données de dictionnaire en position ou un mot-clé arguments à être reçu par la définition de la fonction.

Dans un définition de la fonction ' * ' packs les arguments de position dans un tuple.

Dans un définition de la fonction les '**' packs mot-clé arguments dans un dictionnaire.

38
répondu Karan Ahuja 2016-08-06 19:53:44

* et ** ont une utilisation particulière de la fonction de la liste d'arguments. * implique que l'argument est une liste et ** implique que l'argument est un dictionnaire. Cela permet fonctions pour prendre nombre arbitraire de arguments

20
répondu ronak 2012-09-11 10:59:30

de la documentation Python:

S'il y a plus d'arguments de position qu'il n'y a de slots de paramètres formels, une exception TypeError est soulevée, à moins qu'un paramètre formel utilisant la syntaxe" *identifier " ne soit présent; dans ce cas, ce paramètre formel reçoit un tuple contenant les arguments de position en excès (ou un tuple vide s'il n'y avait pas d'arguments de position en excès).

si un argument de mot-clé ne correspond à un nom de paramètre formel, une exception TypeError est soulevée, sauf si un paramètre formel utilisant la syntaxe "**identifier" est présent; dans ce cas, ce paramètre formel reçoit un dictionnaire contenant les arguments de mot-clé en excès (en utilisant les mots-clés comme clés et les valeurs d'argument comme valeurs correspondantes), ou un (nouveau) dictionnaire vide s'il n'y avait pas d'arguments de mot-clé en excès.

11
répondu Chris Upchurch 2008-08-31 15:07:48

alors que les utilisations pour les opérateurs star/splat ont été expanded en Python 3, j'aime le tableau suivant en ce qui concerne l'utilisation de ces opérateurs avec des fonctions . Le ou les opérateurs splat peuvent être utilisés à la fois dans la fonction construction et dans la fonction appel :

            In function *construction*      In function *call*
=======================================================================
          |  def f(*args):                 |  def f(a, b):
*args     |      for arg in args:          |      return a + b
          |          print(arg)            |  args = (1, 2)
          |  f(1, 2)                       |  f(*args)
----------|--------------------------------|---------------------------
          |  def f(a, b):                  |  def f(a, b):
**kwargs  |      return a + b              |      return a + b
          |  def g(**kwargs):              |  kwargs = dict(a=1, b=2)
          |      return f(**kwargs)        |  f(**kwargs)
          |  g(a=1, b=2)                   |
-----------------------------------------------------------------------

- Ce vraiment juste sert à résumer Lorin Hochstein réponse mais je trouve utile.

8
répondu Brad Solomon 2017-12-02 01:15:43

je veux donner un exemple que d'autres n'ont pas mentionné

* peut aussi déballer une génératrice

un exemple du Document Python3

x = [1, 2, 3]
y = [4, 5, 6]

unzip_x, unzip_y = zip(*zip(x, y))

unzip_x sera [1, 2, 3], unzip_y sera [4, 5, 6]

le zip() reçoit plusieurs args iretables, et renvoie un générateur.

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))
7
répondu Lochu'an Chang 2016-11-08 16:50:20

en Python 3.5, vous pouvez également utiliser cette syntaxe list , dict , tuple , et set affiche (parfois appelé aussi littérales). Voir PEP 488: Généralités supplémentaires sur le déballage .

>>> (0, *range(1, 4), 5, *range(6, 8))
(0, 1, 2, 3, 5, 6, 7)
>>> [0, *range(1, 4), 5, *range(6, 8)]
[0, 1, 2, 3, 5, 6, 7]
>>> {0, *range(1, 4), 5, *range(6, 8)}
{0, 1, 2, 3, 5, 6, 7}
>>> d = {'one': 1, 'two': 2, 'three': 3}
>>> e = {'six': 6, 'seven': 7}
>>> {'zero': 0, **d, 'five': 5, **e}
{'five': 5, 'seven': 7, 'two': 2, 'one': 1, 'three': 3, 'six': 6, 'zero': 0}

permet également de déballer plusieurs itérables dans un appel de fonction unique.

>>> range(*[1, 10], *[2])
range(1, 10, 2)

(merci à mgilson pour le lien PEP.)

6
répondu leewz 2015-12-08 22:29:06

Pour ceux d'entre vous qui apprennent par exemples!

  1. le but de * est de vous donner la capacité de définir une fonction qui peut prendre un nombre arbitraire d'arguments fournis comme une liste (par exemple f(*myList) ).
  2. le but de ** est de vous donner la capacité d'alimenter les arguments d'une fonction en fournissant un dictionnaire (par exemple f(**{'x' : 1, 'y' : 2}) ).

montrons ceci par définir une fonction qui prend deux variables normales x , y , et peut accepter plus d'arguments que myArgs , et peut accepter encore plus d'arguments que myKW . Plus tard, nous montrerons comment alimenter y en utilisant myArgDict .

def f(x, y, *myArgs, **myKW):
    print("# x      = {}".format(x))
    print("# y      = {}".format(y))
    print("# myArgs = {}".format(myArgs))
    print("# myKW   = {}".format(myKW))
    print("# ----------------------------------------------------------------------")

# Define a list for demonstration purposes
myList    = ["Left", "Right", "Up", "Down"]
# Define a dictionary for demonstration purposes
myDict    = {"Wubba": "lubba", "Dub": "dub"}
# Define a dictionary to feed y
myArgDict = {'y': "Why?", 'y0': "Why not?", "q": "Here is a cue!"}

# The 1st elem of myList feeds y
f("myEx", *myList, **myDict)
# x      = myEx
# y      = Left
# myArgs = ('Right', 'Up', 'Down')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# y is matched and fed first
# The rest of myArgDict becomes additional arguments feeding myKW
f("myEx", **myArgDict)
# x      = myEx
# y      = Why?
# myArgs = ()
# myKW   = {'y0': 'Why not?', 'q': 'Here is a cue!'}
# ----------------------------------------------------------------------

# The rest of myArgDict becomes additional arguments feeding myArgs
f("myEx", *myArgDict)
# x      = myEx
# y      = y
# myArgs = ('y0', 'q')
# myKW   = {}
# ----------------------------------------------------------------------

# Feed extra arguments manually and append even more from my list
f("myEx", 4, 42, 420, *myList, *myDict, **myDict)
# x      = myEx
# y      = 4
# myArgs = (42, 420, 'Left', 'Right', 'Up', 'Down', 'Wubba', 'Dub')
# myKW   = {'Wubba': 'lubba', 'Dub': 'dub'}
# ----------------------------------------------------------------------

# Without the stars, the entire provided list and dict become x, and y:
f(myList, myDict)
# x      = ['Left', 'Right', 'Up', 'Down']
# y      = {'Wubba': 'lubba', 'Dub': 'dub'}
# myArgs = ()
# myKW   = {}
# ----------------------------------------------------------------------

mises en garde

  1. ** est exclusivement réservé aux dictionnaires.
  2. Non-argument optionnel affectation a lieu en premier.
  3. vous ne pouvez pas utiliser un argument non-optionnel deux fois.
  4. si applicable, ** doit venir après * , toujours.
5
répondu Miladiouss 2018-08-13 19:43:14

en plus des appels de fonction, *args et **kwargs sont utiles dans les hiérarchies de classe et évitent également d'avoir à écrire la méthode __init__ en Python. Un usage similaire peut être vu dans des cadres comme le code Django.

par exemple,

def __init__(self, *args, **kwargs):
    for attribute_name, value in zip(self._expected_attributes, args):
        setattr(self, attribute_name, value)
        if kwargs.has_key(attribute_name):
            kwargs.pop(attribute_name)

    for attribute_name in kwargs.viewkeys():
        setattr(self, attribute_name, kwargs[attribute_name])

une sous-classe peut alors être

class RetailItem(Item):
    _expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']

class FoodItem(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['expiry_date']

la sous-classe doit alors être instanciée comme

food_item = FoodItem(name = 'Jam', 
                     price = 12.0, 
                     category = 'Foods', 
                     country_of_origin = 'US', 
                     expiry_date = datetime.datetime.now())

Aussi, une sous-classe avec un nouvel attribut qui fait sens seule cette instance de la sous-classe peut appeler la classe de Base __init__ pour désactiver le paramètre attributs. Cela se fait par *args et **kwargs. kwargs utilisé principalement pour que le code soit lisible en utilisant les arguments nommés. Par exemple,

class ElectronicAccessories(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['specifications']
    # Depend on args and kwargs to populate the data as needed.
    def __init__(self, specifications = None, *args, **kwargs):
        self.specifications = specifications  # Rest of attributes will make sense to parent class.
        super(ElectronicAccessories, self).__init__(*args, **kwargs)

qui peut être mis en place comme

usb_key = ElectronicAccessories(name = 'Sandisk', 
                                price = '.00', 
                                category = 'Electronics',
                                country_of_origin = 'CN',
                                specifications = '4GB USB 2.0/USB 3.0')

le code complet est ici

4
répondu Harisankar Krishna Swamy 2018-02-21 09:02:49

un bon exemple d'utilisation des deux dans une fonction est:

>>> def foo(*arg,**kwargs):
...     print arg
...     print kwargs
>>>
>>> a = (1, 2, 3)
>>> b = {'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(*a,**b)
(1, 2, 3)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,**b) 
((1, 2, 3),)
{'aa': 11, 'bb': 22}
>>>
>>>
>>> foo(a,b) 
((1, 2, 3), {'aa': 11, 'bb': 22})
{}
>>>
>>>
>>> foo(a,*b)
((1, 2, 3), 'aa', 'bb')
{}
1
répondu amir jj 2016-10-26 12:48:05

cet exemple vous aiderait à vous souvenir de *args , **kwargs et même super et de l'héritage en Python à la fois.

class base(object):
    def __init__(self, base_param):
        self.base_param = base_param


class child1(base): # inherited from base class
    def __init__(self, child_param, *args) # *args for non-keyword args
        self.child_param = child_param
        super(child1, self).__init__(*args) # call __init__ of the base class and initialize it with a NON-KEYWORD arg

class child2(base):
    def __init__(self, child_param, **kwargs):
        self.child_param = child_param
        super(child2, self).__init__(**kwargs) # call __init__ of the base class and initialize it with a KEYWORD arg

c1 = child1(1,0)
c2 = child2(1,base_param=0)
print c1.base_param # 0
print c1.child_param # 1
print c2.base_param # 0
print c2.child_param # 1
1
répondu thanhtang 2016-11-26 21:09:43

*args et **kwargs : vous permettent de passer un nombre variable d'arguments à une fonction.

*args : est utilisé pour envoyer une liste d'arguments de longueur de variable non-keyworded à la fonction:

def args(normal_arg, *argv):
    print ("normal argument:",normal_arg)

    for arg in argv:
        print("Argument in list of arguments from *argv:", arg)

args('animals','fish','duck','bird')

produira:

normal argument: animals
Argument in list of arguments from *argv: fish
Argument in list of arguments from *argv: duck
Argument in list of arguments from *argv: bird

**kwargs*

**kwargs vous permet de passer la longueur variable des arguments à une fonction. Vous devez utiliser **kwargs si vous souhaitez gérer des arguments nommés dans une fonction.

def who(**kwargs):
    if kwargs is not None:
        for key, value in kwargs.items():
            print ("Your %s is %s." %(key,value))

who (name="Nikola", last_name="Tesla", birthday = "7.10.1856", birthplace = "Croatia")  

produira:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.
0
répondu Harvey 2018-05-01 13:29:58

* signifie recevoir variable d'arguments de la liste

** signifie recevoir variable d'arguments que dictionnaire

utilisé comme suit:

1) simple *

def foo(*args):
    for arg in args:
        print(arg)

foo("two", 3)

sortie:

two
3

2) Maintenant **

def bar(**kwargs):
    for key in kwargs:
        print(key, kwargs[key])

bar(dic1="two", dic2=3)

sortie:

dic1 two
dic2 3
0
répondu ishandutta2007 2018-08-07 18:36:20
  • def foo(param1, *param2): est une méthode qui peut accepter un nombre arbitraire de valeurs pour *param2 ,
  • def bar(param1, **param2): est une méthode qui peut accepter un nombre arbitraire de valeurs avec des clés pour *param2
  • param1 est un paramètre simple.

par exemple, la syntaxe pour mettre en œuvre varargs en Java comme suit:

accessModifier methodName(datatype… arg) {
    // method body
}
0
répondu Premraj 2018-09-02 05:14:05

* args = *aList = tous les éléments d'une liste

**args= ** aDict =tous les éléments dans un dict

-1
répondu JawSaw 2017-12-08 01:43:44