Co oznacza operator Gwiazdy? [duplikat]

Możliwy duplikat:
co oznaczają * args i * * kwargs?

Co oznacza operator * w Pythonie, np. w kodzie zip(*x) lub f(**k)?

  1. Jak jest to obsługiwane wewnętrznie w interpreterze?
  2. Czy to w ogóle wpływa na wydajność? Szybko czy wolno?
  3. Kiedy jest przydatny, a kiedy nie?
  4. czy powinna być używana w deklaracji funkcji czy w wywołaniu?
Author: Peter Mortensen, 2010-05-27

5 answers

Pojedyncza gwiazda * rozpakowuje sekwencję / zbiór do argumentów pozycyjnych, więc możesz to zrobić:

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

values = (1, 2)

s = sum(*values)

To rozpakuje krotkę tak, aby faktycznie wykonywała 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ż połą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 z dokumentacja Pythona.


Dodatkowo można zdefiniować funkcje, które przyjmują argumenty *x i **y, co pozwala funkcji na akceptację dowolnej liczby argumentów pozycyjnych i / lub nazwanych, które nie są specjalnie nazwane 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

Pozwala to określić dużą liczbę opcjonalnych parametrów bez konieczności ich deklarowania.

I znowu możesz połą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
 732
Author: Lasse Vågsæther Karlsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-28 04:18:55

Jedna mała uwaga: to nie są operatory. 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 * * są częścią składni deklaracji i wywołań funkcji.

 36
Author: Ned Batchelder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-27 16:43:37

Nazywa się to rozszerzoną składnią wywołania. Z Dokumentacji :

Jeśli wyrażenie składni * pojawia się w wywołaniu funkcji, wyrażenie musi zostać ocenione do sekwencji. Elementy z tej sekwencji są traktowane tak, jakby były dodatkowymi argumentami pozycyjnymi; jeśli istnieją argumenty pozycyjne x1,..., xN, a wyrażenie ewaluuje do sekwencji y1, ..., yM, jest to równoważne wywołaniu z argumentami pozycyjnymi M+N x1, ..., xN, y1,.., mm.

I:

Jeśli wyrażenie składni * * pojawia się w wywołaniu funkcji, wyrażenie musi zostać ocenione do mapowania, którego zawartość jest traktowana jako dodatkowe argumenty słów kluczowych. W przypadku słowa kluczowego występującego zarówno w wyrażeniu, jak i jako jawny argument słowa kluczowego, pojawia się wyjątek TypeError.

 15
Author: Mark Byers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-27 15:00:57

Uważam to za szczególnie przydatne, gdy chcesz "zapisać" wywołanie funkcji.

Na przykład, załóżmy, że mam kilka testów jednostkowych dla funkcji 'add':

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 na wywołanie 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 być dość brzydki ze wszystkimi instrukcjami if, których potrzebujesz.

Innym miejscem, które jest przydatne, jest definiowanie obiektów fabrycznych (obiekty, które tworzą obiekty dla Ciebie). Załóżmy, że masz jakąś fabrykę klas, która produkuje przedmioty samochodowe i zwraca je. Możesz zrobić to 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 klasy superclass.

 14
Author: Donald Miner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-27 18:45:34

W wywołaniu funkcji pojedyncza gwiazda zamienia listę w osobne argumenty (np. zip(*x) jest taka sama jak zip(x1,x2,x3) if x=[x1,x2,x3]), a gwiazda podwójna zamienia słownik w osobne argumenty słów kluczowych (np. f(**k) jest taka sama jak f(x=my_x, y=my_y) if k = {'x':my_x, 'y':my_y}).

W definicji funkcji jest odwrotnie: pojedyncza gwiazda 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 bierze dowolny liczba argumentów i będą one dostępne poprzez listę x (tzn. jeśli użytkownik wywoła foo(1,2,3), x będzie [1,2,3]) "i def bar(**k) oznacza" bar pobiera dowolną liczbę argumentów słów kluczowych i będą one dostępne poprzez słownik k (tzn. jeśli użytkownik wywoła bar(x=42, y=23), k będzie {'x': 42, 'y': 23})".

 7
Author: sepp2k,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-27 14:18:37