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):
  
                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.  
  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'
  
    	                  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}
  
    	                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.  
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.
   *  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  
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.
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.
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))
  
    	                  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.)
Pour ceux d'entre vous qui apprennent par exemples!
-   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 exemplef(*myList)). -  le but de 
**est de vous donner la capacité d'alimenter les arguments d'une fonction en fournissant un dictionnaire (par exemplef(**{'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
-    
**est exclusivement réservé aux dictionnaires. - Non-argument optionnel affectation a lieu en premier.
 - vous ne pouvez pas utiliser un argument non-optionnel deux fois.
 -   si applicable,  
**doit venir après*, toujours. 
 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
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')
{}
  
    	                 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
  
    	                   *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.
  
    	                   *  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
  
    	                -    
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 -   
param1est un paramètre simple. 
par exemple, la syntaxe pour mettre en œuvre varargs en Java comme suit:
accessModifier methodName(datatype… arg) {
    // method body
}
  
    	                * args = *aList = tous les éléments d'une liste
**args= ** aDict =tous les éléments dans un dict