Domanda

Nelle seguenti definizioni di metodo, cosa significa il file * E ** fare per param2?

def foo(param1, *param2):
def bar(param1, **param2):
È stato utile?

Soluzione

IL *args E **kwargs è un linguaggio comune per consentire un numero arbitrario di argomenti alle funzioni come descritto nella sezione ulteriori informazioni sulla definizione delle funzioni nella documentazione di Python.

IL *args ti fornirà tutti i parametri della funzione come una tupla:

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

IL **kwargs ti darà tuttoargomenti di parole chiave ad eccezione di quelli corrispondenti ad un parametro formale come dizionario.

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

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

Entrambi gli idiomi possono essere combinati con argomenti normali per consentire una serie di argomenti fissi e alcuni variabili:

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

Un altro utilizzo di *l l'idioma è quello decomprimere gli elenchi di argomenti quando si chiama una funzione.

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

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

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

In Python 3 è possibile utilizzare *l sul lato sinistro di un compito (Disimballaggio iterabile esteso), sebbene in questo contesto fornisca una lista anziché una tupla:

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

Anche Python 3 aggiunge una nuova semantica (rif PEP3102):

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

Tale funzione accetta solo 3 argomenti posizionali e tutto il resto * possono essere passati solo come argomenti di parole chiave.

Altri suggerimenti

Vale anche la pena notare che puoi usare * E ** anche quando si chiamano funzioni.Questa è una scorciatoia che ti consente di passare più argomenti a una funzione direttamente utilizzando una lista/tupla o un dizionario.Ad esempio, se hai la seguente funzione:

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

Puoi fare cose come:

>>> 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

Nota:Le chiavi dentro mydict devono essere nominati esattamente come i parametri della funzione foo.Altrimenti lancerà a 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'

Il singolo * significa che può esserci un numero qualsiasi di argomenti posizionali aggiuntivi. foo() può essere invocato come foo(1,2,3,4,5).Nel corpo di foo() param2 è una sequenza contenente 2-5.

Il doppio ** significa che può esserci un numero qualsiasi di parametri con nome aggiuntivi. bar() può essere invocato come bar(1, a=2, b=3).Nel corpo di bar() param2 è un dizionario contenente {'a':2, 'b':3 }

Con il seguente codice:

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)

l'uscita è

1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}

Cosa fa ** (doppia stella) e * (stella) fare per i parametri

Permettono funzioni da definire per accettare e per utenti da passare qualsiasi numero di argomenti, posizionale (*) e la parola chiave (**).

Definizione delle funzioni

*args consente un numero qualsiasi di argomenti posizionali (parametri) opzionali, che verranno assegnati a una tupla denominata args.

**kwargs consente un numero qualsiasi di argomenti di parole chiave opzionali (parametri), che saranno in un dict denominato kwargs.

Puoi (e dovresti) scegliere qualsiasi nome appropriato, ma se l'intenzione è che gli argomenti abbiano una semantica non specifica, args E kwargs sono nomi standard.

Espansione, passaggio di un numero qualsiasi di argomenti

Puoi anche usare *args E **kwargs per passare parametri rispettivamente da liste (o qualsiasi iterabile) e dict (o qualsiasi mappatura).

La funzione che riceve i parametri non deve sapere che questi vengono ampliati.

Ad esempio, xrange di Python 2 non si aspetta esplicitamente *args, ma poiché richiede 3 numeri interi come argomenti:

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

Come altro esempio, possiamo usare l'espansione dict in str.format:

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

Novità in Python 3:Definizione di funzioni con argomenti basati solo su parole chiave

Puoi avere argomenti solo con parole chiave dopo il *args - ad esempio, qui, kwarg2 deve essere fornito come argomento di una parola chiave, non in modo posizionale:

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

Utilizzo:

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

Anche, * può essere utilizzato da solo per indicare che seguono solo argomenti con parole chiave, senza consentire argomenti posizionali illimitati.

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

Qui, kwarg2 ancora una volta deve essere un argomento parola chiave con nome esplicito:

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

E non possiamo più accettare argomentazioni posizionali illimitate perché non ne abbiamo *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

Ancora una volta, più semplicemente, qui richiediamo kwarg da indicare per nome, non per posizione:

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

In questo esempio, lo vediamo se proviamo a passare kwarg posizionalmente, otteniamo un errore:

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

Dobbiamo passare esplicitamente il file kwarg parametro come argomento di una parola chiave.

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

Demo compatibili con Python 2

*args (tipicamente detto "star-args") e **kwargs (le stelle possono essere implicite dicendo "kwargs", ma sii esplicito con "kwargs a doppia stella") sono modi di dire comuni di Python per usare il comando * E ** notazione.Questi nomi di variabili specifici non sono richiesti (ad es.potresti usare *foos E **bars), ma un allontanamento dalle convenzioni probabilmente farà arrabbiare i tuoi colleghi programmatori Python.

Di solito li usiamo quando non sappiamo cosa riceverà la nostra funzione o quanti argomenti potremmo passare, e talvolta anche quando si nomina ogni variabile separatamente diventerebbe molto confuso e ridondante (ma questo è un caso in cui di solito è esplicito meglio che implicito).

Esempio 1

La seguente funzione descrive come possono essere utilizzati e ne dimostra il comportamento.Nota il nome b l'argomento verrà consumato dal secondo argomento posizionale prima di:

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))

Possiamo controllare la guida in linea per la firma della funzione, con help(foo), che ci dice

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

Chiamiamo questa funzione con foo(1, 2, 3, 4, e=5, f=6, g=7)

che stampa:

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}

Esempio 2

Possiamo anche chiamarlo utilizzando un'altra funzione, nella quale ci limitiamo a fornire 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) stampe:

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}

Esempio 3:utilizzo pratico nei decoratori

OK, forse non stiamo ancora vedendo l'utilità.Quindi immagina di avere diverse funzioni con codice ridondante prima e/o dopo il codice differenziante.Le seguenti funzioni denominate sono solo pseudocodice a scopo illustrativo.

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

Potremmo essere in grado di gestirlo in modo diverso, ma possiamo certamente eliminare la ridondanza con un decoratore, quindi il nostro esempio seguente dimostra come *args E **kwargs può essere molto utile:

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

E ora ogni funzione inserita può essere scritta in modo molto più conciso, poiché abbiamo eliminato la ridondanza:

@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)

E prendendo in considerazione il nostro codice, which *args E **kwargs ci consente di farlo, riduciamo le righe di codice, miglioriamo la leggibilità e la manutenibilità e disponiamo di posizioni canoniche uniche per la logica nel nostro programma.Se dobbiamo modificare qualsiasi parte di questa struttura, abbiamo un posto in cui apportare ogni modifica.

Cerchiamo innanzitutto di capire cosa sono gli argomenti posizionali e gli argomenti di parole chiave.Di seguito è riportato un esempio di definizione della funzione con Argomenti posizionali.

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

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

Quindi questa è una definizione di funzione con argomenti posizionali.Puoi chiamarlo anche con parole chiave/argomenti con nome:

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

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

Studiamo ora un esempio di definizione di funzione con argomenti di parole chiave:

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
-------------------------

Puoi chiamare questa funzione anche con argomenti posizionali:

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

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

Quindi ora conosciamo le definizioni di funzioni con argomenti posizionali e con parole chiave.

Studiamo ora l'operatore '*' e l'operatore '**'.

Tieni presente che questi operatori possono essere utilizzati in 2 aree:

UN) chiamata di funzione

B) definizione della funzione

L'uso dell'operatore '*' e dell'operatore '**' in chiamata di funzione.

Andiamo direttamente a un esempio e poi discutiamone.

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.

Quindi ricorda

quando l'operatore '*' o '**' viene utilizzato in a chiamata di funzione -

L'operatore '*' decomprime la struttura dei dati come una lista o una tupla negli argomenti richiesti dalla definizione della funzione.

L'operatore '**' scompatta un dizionario negli argomenti necessari alla definizione della funzione.

Studiamo ora l'uso dell'operatore '*' definizione della funzione.Esempio:

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

In funzione definizione l'operatore '*' racchiude gli argomenti ricevuti in una tupla.

Vediamo ora un esempio di '**' utilizzato nella definizione della funzione:

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

In funzione definizione L'operatore '**' racchiude gli argomenti ricevuti in un dizionario.

Quindi ricorda:

In un chiamata di funzione IL '*' disimballa struttura dati di tupla o lista in argomenti posizionali o parole chiave da ricevere dalla definizione di funzione.

In un chiamata di funzione IL '**' disimballa struttura dati del dizionario in argomenti posizionali o parole chiave da ricevere dalla definizione di funzione.

In un definizione della funzione IL '*' pacchi argomenti posizionali in una tupla.

In un definizione della funzione IL '**' pacchi argomenti di parole chiave in un dizionario.

* E ** hanno un uso speciale nell'elenco degli argomenti della funzione. *implica che l'argomento è una lista e ** implica che l'argomento è un dizionario.Ciò consente alle funzioni di assumere un numero arbitrario di argomenti

Mentre gli usi per gli operatori stella/simbolo sono stati allargato in Python 3, mi piace la tabella seguente in quanto si riferisce all'uso di questi operatori con funzioni.Gli operatori splat possono essere utilizzati sia all'interno di function costruzione e nella funzione chiamata:

            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)                   |
-----------------------------------------------------------------------

Questo in realtà serve solo a riassumere il pensiero di Lorin Hochstein risposta ma lo trovo utile.

Per quelli di voi che imparano dagli esempi!

  1. Lo scopo di * è darti la possibilità di definire una funzione che può accettare un numero arbitrario di argomenti forniti come elenco (ad es. f(*myList) ).
  2. Lo scopo di ** è darti la possibilità di alimentare gli argomenti di una funzione fornendo un dizionario (ad es. f(**{'x' : 1, 'y' : 2}) ).

Mostriamolo definendo una funzione che accetta due variabili normali x, y, e può accettare più argomenti come myArgs, e può accettare ancora più argomenti come myKW.Più tardi mostreremo come nutrirlo y utilizzando 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   = {}
# ----------------------------------------------------------------------

Avvertenze

  1. ** è riservato esclusivamente ai dizionari.
  2. L'assegnazione degli argomenti non facoltativi avviene per prima.
  3. Non è possibile utilizzare un argomento non facoltativo due volte.
  4. Se applicabile, ** deve venire dopo *, Sempre.

Dalla documentazione di Python:

Se sono presenti più argomenti posizionali che slot di parametri formali, viene sollevata un'eccezione TypeError, a meno che non sia presente un parametro formale che utilizza la sintassi "*identifier";in questo caso, quel parametro formale riceve una tupla contenente gli argomenti posizionali in eccesso (o una tupla vuota se non ci sono argomenti posizionali in eccesso).

Se un argomento di parola chiave non corrisponde al nome di un parametro formale, viene sollevata un'eccezione TypeError, a meno che non sia presente un parametro formale che utilizza la sintassi "**identifier";in questo caso, quel parametro formale riceve un dizionario contenente gli argomenti delle parole chiave in eccesso (utilizzando le parole chiave come chiavi e i valori degli argomenti come valori corrispondenti), o un (nuovo) dizionario vuoto se non ci sono argomenti delle parole chiave in eccesso.

In Python 3.5, puoi anche usare questa sintassi in list, dict, tuple, E set display (a volte chiamati anche valori letterali).Vedere PEP488:Ulteriori generalizzazioni di disimballaggio.

>>> (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}

Consente inoltre di decomprimere più iterabili in una singola chiamata di funzione.

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

(Grazie a mgilson per il collegamento PEP.)

Voglio fare un esempio che altri non hanno menzionato

* può anche decomprimere a Generatore

Un esempio dal documento Python3

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

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

unzip_x sarà [1, 2, 3], unzip_y sarà [4, 5, 6]

zip() riceve più argomenti irretabili e restituisce un generatore.

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))

Oltre alle chiamate di funzione, *args e **kwargs sono utili nelle gerarchie di classi ed evitano anche di dover scrivere __init__ metodo in Python.Un utilizzo simile può essere visto in framework come il codice Django.

Per esempio,

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])

Una sottoclasse può quindi essere

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 sottoclasse verrà quindi istanziata come

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

Inoltre, una sottoclasse con un nuovo attributo che ha senso solo per quell'istanza della sottoclasse può chiamare la classe Base __init__ per scaricare l'impostazione degli attributi.Questo viene fatto tramite *args e **kwargs.kwargs viene utilizzato principalmente in modo che il codice sia leggibile utilizzando argomenti con nome.Per esempio,

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)

che può essere istanziato come

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

Il codice completo è Qui

* significa ricevere argomenti variabili come elenco

** significa ricevere argomenti variabili come dizionario

Usato come il seguente:

1) singolo *

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

foo("two", 3)

Produzione:

two
3

2) Ora **

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

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

Produzione:

dic1 two
dic2 3

Un buon esempio di utilizzo di entrambi in una funzione è:

>>> 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')
{}

Questo esempio ti aiuterà a ricordare *args, **kwargs e persino super ed ereditarietà in Python contemporaneamente.

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

TL;DR

Contiene gli argomenti passati alla funzione list E dict rispettivamente all'interno del corpo della funzione.Quando definisci una firma di funzione come questa:

def func(*args, **kwds):
    # do stuff

può essere chiamato con qualsiasi numero di argomenti e argomenti con parole chiave.Gli argomenti diversi dalle parole chiave vengono raggruppati in un elenco chiamato args all'interno del corpo della funzione e gli argomenti della parola chiave vengono racchiusi in un dict chiamato kwds all'interno del corpo della funzione.

func("this", "is a list of", "non-keyowrd", "arguments", keyword="ligma", options=[1,2,3])

ora all'interno del corpo della funzione, quando viene chiamata la funzione, ci sono due variabili locali, args che è una lista avente valore ["this", "is a list of", "non-keyword", "arguments"] E kwds il quale è un dict avere valore {"keyword" : "ligma", "options" : [1,2,3]}


Funziona anche al contrario, cioèdal lato chiamante.ad esempio se hai una funzione definita come:

def f(a, b, c, d=1, e=10):
    # do stuff

puoi chiamarlo decomprimendo gli iterabili o le mappature che hai nell'ambito della chiamata:

iterable = [1, 20, 500]
mapping = {"d" : 100, "e": 3}
f(*iterable, **mapping)
# That call is equivalent to
f(1, 20, 500, d=100, e=3)

*args E **kwargs:consentono di passare un numero variabile di argomenti a una funzione.

*args:viene utilizzato per inviare un elenco di argomenti di lunghezza variabile senza parole chiave alla funzione:

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')

Produrrà:

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 consente di passare argomenti di lunghezza variabile con parole chiave a una funzione.Dovresti usare **kwargs se vuoi gestire argomenti con nome in una funzione.

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")  

Produrrà:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.
  • def foo(param1, *param2): è un metodo che può accettare un numero arbitrario di valori per *param2,
  • def bar(param1, **param2): è un metodo che può accettare un numero arbitrario di valori con chiavi per *param2
  • param1 è un parametro semplice

Ad esempio, la sintassi per l'implementazione varargs in Java come segue:

accessModifier methodName(datatype… arg) {
    // method body
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top