pyplot - title matplotlib python




Cosa significa l'operatore stella? (4)

In una chiamata di funzione la stella singola trasforma una lista in argomenti separati (es. zip(*x) è uguale a zip(x1,x2,x3) se x=[x1,x2,x3] ) e la doppia stella trasforma un dizionario in argomenti di parole separate (es. f(**k) è uguale a f(x=my_x, y=my_y) se k = {'x':my_x, 'y':my_y} .

In una definizione di funzione è il contrario: la singola stella trasforma un numero arbitrario di argomenti in una lista e il doppio inizio trasforma un numero arbitrario di argomenti di parole chiave in un dizionario. Ad esempio, def foo(*x) significa che "foo prende un numero arbitrario di argomenti e saranno accessibili attraverso la lista x (cioè se l'utente chiama foo(1,2,3) , x sarà [1,2,3] ) "e def bar(**k) significa" la barra prende un numero arbitrario di argomenti di parole chiave e saranno accessibili attraverso il dizionario k (cioè se l'utente chiama la bar(x=42, y=23) , k sarà {'x': 42, 'y': 23} ) ".

Cosa significa l'operatore * in Python, come nel codice come zip(*x) o f(**k) ?

  1. Come viene gestito internamente nell'interprete?
  2. Ha un impatto sulle prestazioni? È veloce o lento?
  3. Quando è utile e quando non lo è?
  4. Dovrebbe essere usato in una dichiarazione di funzione o in una chiamata?

La stella singola * spacchetta la sequenza / raccolta in argomenti posizionali, così puoi farlo:

def sum(a, b):
    return a + b

values = (1, 2)

s = sum(*values)

Questo decomprimerà la tupla in modo che venga effettivamente eseguita come:

s = sum(1, 2)

La doppia stella ** fa la stessa cosa, usando solo un dizionario e quindi argomenti con nome:

values = { 'a': 1, 'b': 2 }
s = sum(**values)

Puoi anche combinare:

def sum(a, b, c, d):
    return a + b + c + d

values1 = (1, 2)
values2 = { 'c': 10, 'd': 15 }
s = sum(*values1, **values2)

verrà eseguito come:

s = sum(1, 2, c=10, d=15)

Vedi anche la sezione 4.7.4 - Disimballaggio degli elenchi di argomenti della documentazione di Python.

Inoltre, è possibile definire le funzioni per accettare gli argomenti *x **y , ciò consente a una funzione di accettare qualsiasi numero di argomenti posizionali e / o denominati che non siano specificatamente denominati nella dichiarazione.

Esempio:

def sum(*values):
    s = 0
    for v in values:
        s = s + v
    return s

s = sum(1, 2, 3, 4, 5)

o con ** :

def get_a(**values):
    return values['a']

s = get_a(a=1, b=2)      # returns 1

questo può consentire di specificare un numero elevato di parametri facoltativi senza doverli dichiarare.

E ancora, puoi combinare:

def sum(*values, **options):
    s = 0
    for i in values:
        s = s + i
    if "neg" in options:
        if options["neg"]:
            s = -s
    return s

s = sum(1, 2, 3, 4, 5)            # returns 15
s = sum(1, 2, 3, 4, 5, neg=True)  # returns -15
s = sum(1, 2, 3, 4, 5, neg=False) # returns 15

Trovo questo particolarmente utile per quando si desidera 'memorizzare' una chiamata di funzione.

Ad esempio, supponiamo di avere alcuni test unitari per una funzione 'aggiungi':

def add(a, b): return a + b
tests = { (1,4):5, (0, 0):0, (-1, 3):3 }
for test, result in tests.items():
   print 'test: adding', test, '==', result, '---', add(*test) == result

Non c'è altro modo per chiamare add, oltre a fare manualmente qualcosa come add (test [0], test [1]), che è brutto. Inoltre, se ci sono un numero variabile di variabili, il codice potrebbe diventare piuttosto brutto con tutte le istruzioni if ​​necessarie.

Un altro posto utile è la definizione di oggetti Factory (oggetti che creano oggetti per te). Supponiamo che tu abbia una fabbrica di classe, che renda oggetti auto e li restituisca. Si può fare in modo che myFactory.make_car ('red', 'bmw', '335ix') crei Car ('red', 'bmw', '335ix'), quindi lo restituisce.

def make_car(*args):
   return Car(*args)

Ciò è utile anche quando si desidera chiamare un costruttore di una superclasse.


Un piccolo punto: questi non sono operatori. Gli operatori sono utilizzati nelle espressioni per creare nuovi valori da valori esistenti (ad esempio 1 + 2 diventa 3. Le * e ** qui fanno parte della sintassi delle dichiarazioni di funzioni e delle chiamate.





kwargs