Co * * (gwiazda podwójna/gwiazdka) i * (gwiazda/gwiazdka) robią dla parametrów?

W poniższych definicjach metod, co * i ** robią dla param2?

def foo(param1, *param2):
def bar(param1, **param2):
Author: Florian_1990, 2008-08-31

18 answers

*args i **kwargs jest powszechnym idiomem pozwalającym na dowolną liczbę argumentów funkcjom opisanym w sekcji więcej o definiowaniu funkcji w dokumentacji Pythona.

*args poda wszystkie parametry funkcji jako krotkę :

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

**kwargs da Ci wszystko argumenty słów kluczowych z wyjątkiem tych odpowiadających formalnemu parametrowi jako słownikowi.

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

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

Oba idiomy można mieszać z normalnymi argumentami do pozwala na zbiór stałych i zmiennych argumentów:

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

Innym zastosowaniem idiomu *ljest rozpakowanie listy argumentów podczas wywoływania funkcji.

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

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

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

W Pythonie 3 możliwe jest użycie *lpo lewej stronie przypisania ( Extended iterable Unpacking ), chociaż w tym kontekście daje listę zamiast krotki:

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

Również Python 3 dodaje nowy semantic (refer PEP 3102):

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

Taka funkcja przyjmuje tylko 3 argumenty pozycyjne, a wszystko po * może być przekazywane tylko jako argumenty słów kluczowych.

 1618
Author: Peter Hoffmann,
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
2017-05-28 12:54:20

Warto również zauważyć, że możesz używać * i ** również podczas wywoływania funkcji. Jest to skrót, który pozwala przekazać wiele argumentów do funkcji bezpośrednio za pomocą listy/krotki lub słownika. Na przykład, jeśli masz następującą funkcję:

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

Możesz robić takie rzeczy jak:

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

Uwaga: klucze w {[5] } muszą być nazwane dokładnie tak, jak parametry funkcji foo. W przeciwnym razie rzuci 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'
 468
Author: Lorin Hochstein,
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
2018-03-07 01:53:17

Pojedynczy * oznacza, że może istnieć dowolna liczba dodatkowych argumentów pozycyjnych. foo() można wywoływać jak foo(1,2,3,4,5). W ciele foo () param2 jest sekwencją zawierającą 2-5.

Podwójne * * oznacza, że może być dowolna liczba dodatkowych nazwanych parametrów. bar() można wywoływać jak bar(1, a=2, b=3). W ciele bar () param2 znajduje się słownik zawierający {"a": 2, "b": 3 }

O następującym kodzie:

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)

Wyjście to

1
(2, 3, 4, 5)
1
{'a': 2, 'b': 3}
 135
Author: nickd,
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
2008-08-31 15:20:21

Co robi ** (gwiazda podwójna) i * (gwiazda) dla parametrów

Pozwalają na zdefiniowanie funkcji tak, aby przyjmowały , a dla użytkowników przekazywały dowolną liczbę argumentów, positional (*) i keyword (**).

Definiowanie Funkcji

*args pozwala na dowolną liczbę opcjonalnych argumentów pozycyjnych (parametrów), które zostaną przypisane do krotki o nazwie args.

**kwargs pozwala na dowolną liczbę opcjonalnych słów kluczowych argumenty (parametry), które będą w dict o nazwie kwargs.

Możesz (i powinieneś) wybrać dowolną odpowiednią nazwę, ale jeśli intencją jest, aby argumenty były nieswoistymi semantykami, args i kwargs są nazwami standardowymi.

Rozszerzenie, przekazywanie dowolnej liczby argumentów

Możesz również użyć *args i **kwargs, aby przekazać parametry odpowiednio z list (lub dowolnych iterowalnych) i dictów (lub dowolnego mapowania).

Funkcja odbierająca parametry NIE trzeba wiedzieć, że są one rozszerzane.

Na przykład, Xrange Pythona 2 nie oczekuje jawnie *args, ale ponieważ przyjmuje 3 liczby całkowite jako argumenty:

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

Jako kolejny przykład możemy użyć rozszerzenia dict w str.format:

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

Nowość w Pythonie 3: definiowanie funkcji za pomocą argumentów tylko dla słów kluczowych

Możesz mieć tylko argumenty słowa kluczowego po *args - na przykład tutaj, kwarg2 musi być podany jako argument słowa kluczowego-Nie pozycja:

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

Użycie:

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

Również, * może być użyte samo w sobie, aby wskazać, że za słowem kluczowym podążają tylko argumenty, nie pozwalając na nieograniczoną liczbę argumentów pozycyjnych.

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

Tutaj, kwarg2 ponownie musi być jawnie nazwany argument słowa kluczowego:

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

I nie możemy już przyjmować nieograniczonych argumentów pozycyjnych, ponieważ nie mamy *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

Ponownie, prościej, tutaj wymagamy kwarg aby być podane po imieniu, a nie pozycja:

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

W tym przykładzie widzimy, że jeśli spróbujemy przejść kwarg pozycyjnie, otrzymamy błąd:

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

Musimy jawnie przekazać parametr kwarg jako argument słowa kluczowego.

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

Python 2 compatible demos

*args (w Pythonie występują dwa typy gwiazd: gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe, Gwiazdy gwiazdowe. Te specyficzne nazwy zmiennych nie są wymagane (np. możesz użyć *foos i **bars), ale odejście od konwencji może rozwścieczyć innych programistów Pythona.

Zazwyczaj używamy ich, gdy nie wiemy, co nasza funkcja otrzyma lub ile argumentów możemy przekazać, a czasami nawet nazywając każdą zmienną osobno, robi się to bardzo niechlujne i zbędne (ale jest to przypadek, w którym zwykle jawne jest lepsze niż niejawne).

Przykład 1

Następujące funkcja opisuje, w jaki sposób mogą być używane i demonstruje zachowanie. Uwaga argument o nazwie b zostanie wykorzystany przez drugi argument pozycyjny przed :

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))
Możemy sprawdzić w Pomocy online sygnaturę funkcji za pomocą help(foo), która mówi nam
foo(a, b=10, *args, **kwargs)

Nazwijmy tę funkcję foo(1, 2, 3, 4, e=5, f=6, g=7)

Który drukuje:

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}

Przykład 2

Możemy ją również wywołać za pomocą innej funkcji, do której po prostu podajemy 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) nadruki:

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}

Przykład 3: praktyczne zastosowanie w dekoratorach

OK, więc może nie widzimy jeszcze użyteczności. Wyobraź sobie więc, że masz kilka funkcji z nadmiarowym kodem przed i / lub po kodzie różnicującym. Poniższe funkcje nazwane są tylko pseudokodem dla celów ilustracyjnych.

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
Możemy być w stanie poradzić sobie z tym inaczej, ale z pewnością możemy wyodrębnić redundancję za pomocą dekoratora, a więc nasze poniższy przykład pokazuje, jak *args i **kwargs mogą być bardzo przydatne:
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
A teraz każda zawinięta funkcja może być napisana znacznie zwięźle, ponieważ uwzględniliśmy redundancję:]}
@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)

I faktorując nasz kod, Co *args i **kwargs pozwala nam to zrobić, zmniejszamy linie kodu, poprawiamy czytelność i konserwację oraz mamy jedyne kanoniczne lokalizacje dla logiki w naszym programie. Jeśli musimy zmienić jakąkolwiek część tej struktury, mamy jedno miejsce, w którym dokonaj każdej zmiany.

 112
Author: Aaron Hall,
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
2016-12-20 20:21:05

Najpierw zrozummy, czym są argumenty pozycyjne i argumenty słów kluczowych. Poniżej znajduje się przykład definicji funkcji z argumentami pozycyjnymi .

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

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

Jest to więc definicja funkcji z argumentami pozycyjnymi. Można go wywołać za pomocą słów kluczowych/nazwanych argumentów:

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

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

Przyjrzyjmy się teraz przykładowi definicji funkcji z argumentami słów kluczowych :

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

Możesz wywołać tę funkcję z argumentami pozycyjnymi jako cóż:

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

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

Znamy więc definicje funkcji z argumentami pozycyjnymi i kluczowymi.

Przyjrzyjmy się teraz operatorowi ' * 'i'**'.

Należy pamiętać, że te operatory mogą być używane w 2 obszarach:

A) wywołanie funkcji

B) definicja funkcji

Użycie operatora '*' i operatora '**' w wywołaniu funkcji .

Przejdźmy od razu do przykładu, a następnie przedyskutujmy go.
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.

Więc remember

Gdy operator ' * ' lub '* * ' jest używany w wywołaniu funkcji -

Operator'* ' rozpakowuje strukturę danych, taką jak lista lub krotka, na argumenty wymagane przez definicję funkcji.

Operator'** ' rozpakowuje słownik do argumentów wymaganych przez definicję funkcji.

Teraz przestudiujmy użycie operatora ' * ' w definicji funkcji . Przykład:

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

W funkcji definicja operator ' * ' pakuje otrzymane argumenty do krotka.

Teraz zobaczmy przykład '* * ' użyty w definicji funkcji:

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

W definicji funkcji operator '* * ' pakuje otrzymane argumenty do słownika.

Więc pamiętaj:

W wywołaniu funkcji ' * ' rozpakowuje strukturę danych krotki lub listy do argumentów pozycyjnych lub słów kluczowych, które mają być odebrane przez definicję funkcji.

W wywołaniu funkcji '* * ' rozpakowuje strukturę danych słownika do argumentów pozycyjnych lub słów kluczowych, które mają być odebrane przez definicję funkcji.

W definicji funkcji ' * 'pakuje argumenty pozycyjne w krotkę.

W definicji funkcji '* * ' pakuje argumenty słów kluczowych do słownika.

 38
Author: Karan Ahuja,
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
2016-08-06 19:53:44

* i ** mają specjalne zastosowanie na liście argumentów funkcji. * implikuje, że argument jest listą i ** implikuje, że argument jest słownikiem. Dzięki temu funkcje mogą przyjmować dowolną liczbę argumenty

 20
Author: ronak,
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
2012-09-11 10:59:30

Z Dokumentacji Pythona:

Jeśli jest więcej argumentów pozycyjnych niż formalnych, wywołany jest wyjątek TypeError, chyba że obecny jest parametr formalny wykorzystujący składnię "*identifier"; w tym przypadku ten parametr formalny otrzymuje krotkę zawierającą nadmiarowe argumenty pozycyjne (lub pustą krotkę, jeśli nie było nadmiarowych argumentów pozycyjnych).

Jeśli jakikolwiek argument słowa kluczowego nie odpowiada formalnej nazwie parametru, TypeError wyjątek jest podnoszony, chyba że jest obecny parametr formalny wykorzystujący składnię "* * identifier"; w tym przypadku parametr formalny otrzymuje słownik zawierający nadmiarowe argumenty słów kluczowych (używając słów kluczowych jako kluczy i wartości argumentów jako odpowiadających im wartości) lub (nowy) pusty słownik, jeśli nie ma nadmiarowych argumentów słów kluczowych.

 11
Author: Chris Upchurch,
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
2008-08-31 15:07:48

Podczas gdy zastosowania operatorów star / splat zostały Rozszerzone w Pythonie 3, podoba mi się poniższa tabela, ponieważ odnosi się ona do użycia tych operatorów z funkcjami. Operator (y) splat może być używany zarówno w konstrukcji funkcji jak i w funkcji wywołanie :

            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)                   |
-----------------------------------------------------------------------
To naprawdę służy podsumowaniu odpowiedzi Lorina Hochsteina, ale uważam, że jest to pomocne.
 8
Author: Brad Solomon,
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
2017-12-02 01:15:43

Chcę podać przykład, o którym inni nie wspominali

* można również rozpakować generator

Przykład z dokumentu Python3

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

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

Unzip_x będzie [1, 2, 3], unzip_y będzie [4, 5, 6]

Zip () otrzymuje wiele iretable args i zwraca generator.

zip(*zip(x,y)) -> zip((1, 4), (2, 5), (3, 6))
 7
Author: Lochu'an Chang,
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
2016-11-08 16:50:20

W Pythonie 3.5 można również użyć tej składni w list, dict, tuple, i set wyświetla (czasem nazywane też literałami). Zobacz PEP 488: dodatkowe uogólnienia rozpakowywania .

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

Pozwala również na rozpakowanie wielu iterabli w jednym wywołaniu funkcji.

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

(podziękowania dla mgilson za link PEP.)

 6
Author: leewz,
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
2015-12-08 22:29:06

Dla tych z Was, którzy uczą się na przykładach!

  1. celem * jest umożliwienie zdefiniowania funkcji, która może przyjmować dowolną liczbę argumentów podanych jako lista(np. f(*myList)).
  2. celem ** jest umożliwienie podawania argumentów funkcji poprzez dostarczenie słownika(np. f(**{'x' : 1, 'y' : 2})).

Pokażmy to definiując funkcję, która przyjmuje dwie zmienne normalne x, y, i może przyjąć więcej argumentów jako myArgs, i może przyjąć jeszcze więcej argumentów jako myKW. Później pokażemy, jak karmić y za pomocą 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   = {}
# ----------------------------------------------------------------------

Caveats

  1. ** jest zarezerwowane wyłącznie dla słowników.
  2. nieobowiązkowe przypisanie argumentów następuje jako pierwsze.
  3. nie można użyć argumentu nieobowiązkowego dwa razy.
  4. jeśli dotyczy, ** musi nastąpić po *, zawsze.
 5
Author: Miladiouss,
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
2018-08-13 19:43:14

Oprócz wywołań funkcji, *args i **kwargs są użyteczne w hierarchii klas, a także unikają pisania metody __init__ w Pythonie. Podobne użycie można zobaczyć w frameworkach takich jak kod Django.

Na przykład,

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

Podklasa może być

class RetailItem(Item):
    _expected_attributes = Item._expected_attributes + ['name', 'price', 'category', 'country_of_origin']

class FoodItem(RetailItem):
    _expected_attributes = RetailItem._expected_attributes +  ['expiry_date']

Podklasa zostanie utworzona jako

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

Również podklasa z nowym atrybutem, który ma sens tylko dla tej instancji podklasy, może wywołać klasę bazową __init__, aby odciążyć ustawienie atrybutów. To jest zrobione przez * args i * * kwargs. kwargs używany jest głównie po to, aby Kod był czytelny przy użyciu nazwanych argumentów. Na przykład,

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)

Które można zainstalować jako

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

Kompletny kod to tutaj

 4
Author: Harisankar Krishna Swamy,
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
2018-02-21 09:02:49

Dobrym przykładem użycia obu funkcji jest:

>>> 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')
{}
 1
Author: amir jj,
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
2016-10-26 12:48:05

Ten przykład pomoże Ci zapamiętać *args, **kwargs a nawet super i dziedziczenie w Pythonie na raz.

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
 1
Author: thanhtang,
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
2016-11-26 21:09:43

*args and **kwargs: pozwala przekazać zmienną liczbę argumentów do funkcji.

*args: jest używany do wysyłania listy argumentów o zmiennej długości bez napisu kluczowego do funkcji:

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

Wyprodukuje:

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 pozwala na przekazanie zmiennej długości argumentów napisanych słowami kluczowymi do funkcji. Powinieneś użyć **kwargs, jeśli chcesz obsługiwać nazwane argumenty w funkcji.

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

Wyprodukuje:

Your name is Nikola.
Your last_name is Tesla.
Your birthday is 7.10.1856.
Your birthplace is Croatia.
 0
Author: Harvey,
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
2018-05-01 13:29:58

* oznacza otrzymywanie argumentów zmiennych jako listy

** oznacza otrzymywanie argumentów zmiennych jako słownik

Używane w następujący sposób:

1) single *

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

foo("two", 3)

Wyjście:

two
3

2) Teraz **

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

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

Wyjście:

dic1 two
dic2 3
 0
Author: ishandutta2007,
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
2018-08-07 18:36:20
  • def foo(param1, *param2): jest metodą, która może przyjmować dowolną liczbę wartości dla *param2,
  • def bar(param1, **param2): jest metodą, która może przyjmować dowolną ilość wartości z kluczami dla *param2
  • param1 jest prostym parametrem.

Na przykład składnia implementacji varargs w Javie wygląda następująco:

accessModifier methodName(datatype… arg) {
    // method body
}
 0
Author: Premraj,
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
2018-09-02 05:14:05

*args = * aList = wszystkie elementy listy

**args= * * aDict =wszystkie elementy w dict

 -1
Author: JawSaw,
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
2017-12-08 01:43:44