Co oznacza *
operator w Pythonie, na przykład w kodzie, takim jak zip(*x)
lub f(**k)
?
- Jak to jest obsługiwane wewnętrznie przez tłumacza?
- Czy to w ogóle wpływa na wydajność? Czy to szybko czy wolno?
- Kiedy jest przydatny, a kiedy nie?
- Powinien być używany w deklaracji funkcji czy w wywołaniu?
*
i**
operatora, że nie mają nic wspólnego z tym składni.[*a, b, *c]
Lub{**d1, **d2}
), będziesz chciał czytać gwiazdkę w definicjach krotki, listy i zestawów, podwójną gwiazdkę w definicji dykt , która jest specyficzna dla użycia poza wywołaniami funkcji i definicjami funkcji . W przypadku wcześniejszego PEP 3132 zobacz Przypisanie wielokrotnego rozpakowywania w Pythonie, gdy nie znasz długości sekwencji .Odpowiedzi:
Pojedyncza gwiazda
*
rozpakowuje sekwencję / kolekcję na argumenty pozycyjne, więc możesz to zrobić:def sum(a, b): return a + b values = (1, 2) s = sum(*values)
Spowoduje to rozpakowanie krotki, aby faktycznie była wykonywana jako:
s = sum(1, 2)
Gwiazda podwójna
**
robi to samo, używając tylko słownika i nazwanych argumentów:values = { 'a': 1, 'b': 2 } s = sum(**values)
Możesz również łączyć:
def sum(a, b, c, d): return a + b + c + d values1 = (1, 2) values2 = { 'c': 10, 'd': 15 } s = sum(*values1, **values2)
wykona jako:
s = sum(1, 2, c=10, d=15)
Zobacz także sekcję 4.7.4 - Rozpakowywanie list argumentów w dokumentacji Pythona.
Dodatkowo możesz zdefiniować funkcje do pobrania
*x
i**y
argumenty, dzięki czemu funkcja może zaakceptować dowolną liczbę pozycyjnych i / lub nazwanych argumentów, które nie są wyraźnie wymienione w deklaracji.Przykład:
def sum(*values): s = 0 for v in values: s = s + v return s s = sum(1, 2, 3, 4, 5)
lub z
**
:def get_a(**values): return values['a'] s = get_a(a=1, b=2) # returns 1
umożliwia to określenie dużej liczby parametrów opcjonalnych bez konieczności ich deklarowania.
I znowu możesz łączyć:
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
źródło
s = sum((1, 2, 3, 4, 5))
czys = sum([1, 2, 3, 4, 5])
The*values
opcja sprawia, że wygląd wywołanie jak to trwa kilka argumentów, ale są one zapakowane w kolekcji dla kodu funkcji.Jedna mała uwaga: to nie są operatorzy. Operatory są używane w wyrażeniach do tworzenia nowych wartości z istniejących wartości (na przykład 1 + 2 staje się 3. * I ** tutaj są częścią składni deklaracji funkcji i wywołań).
źródło
Uważam, że jest to szczególnie przydatne, gdy chcesz „przechowywać” wywołanie funkcji.
Na przykład załóżmy, że mam kilka testów jednostkowych dla funkcji „dodaj”:
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
Nie ma innego sposobu wywołania add, poza ręcznym wykonaniem czegoś takiego jak add (test [0], test [1]), co jest brzydkie. Ponadto, jeśli istnieje zmienna liczba zmiennych, kod może stać się dość brzydki ze wszystkimi potrzebnymi instrukcjami if.
Innym miejscem, w którym jest to przydatne, jest definiowanie obiektów Factory (obiektów, które tworzą obiekty dla Ciebie). Załóżmy, że masz jakąś klasę Factory, która tworzy obiekty Car i zwraca je. Można to zrobić tak, że myFactory.make_car („red”, „bmw”, „335ix”) tworzy samochód („red”, „bmw”, „335ix”), a następnie zwraca go.
def make_car(*args): return Car(*args)
Jest to również przydatne, gdy chcesz wywołać konstruktor nadklasy.
źródło
Nazywa się to rozszerzoną składnią wywołania. Z dokumentacji :
i:
źródło
apply()
funkcjąW wywołaniu funkcji pojedyncza gwiazdka zamienia listę w osobne argumenty (np.
zip(*x)
Jest tym samym cozip(x1,x2,x3)
ifx=[x1,x2,x3]
), a podwójna gwiazdka zamienia słownik w osobne argumenty słów kluczowych (np.f(**k)
Jest takie samo, jakf(x=my_x, y=my_y)
gdybyk = {'x':my_x, 'y':my_y}
.W definicji funkcji jest odwrotnie: pojedyncza gwiazdka zamienia dowolną liczbę argumentów w listę, a podwójny start zamienia dowolną liczbę argumentów słów kluczowych w słownik. Np.
def foo(*x)
Oznacza "foo przyjmuje dowolną liczbę argumentów i będą one dostępne przez listę x (tj. Jeśli użytkownik wywołafoo(1,2,3)
,x
będzie[1,2,3]
)" idef bar(**k)
oznacza "bar przyjmuje dowolną liczbę argumentów słów kluczowych i będą one dostępne przez słownik k (tj. jeśli użytkownik dzwonibar(x=42, y=23)
,k
będzie{'x': 42, 'y': 23}
) ”.źródło
def foo(*x)
* x daje krotkę, a nie listę.