Użycie * args i * * kwargs [duplikat]

to pytanie ma już odpowiedzi tutaj : co * *(gwiazda podwójna/gwiazdka) i * (gwiazda/gwiazdka) robią dla parametrów? (22 odpowiedzi) Zamknięte 7 lat temu.

Więc mam trudności z pojęciem *args i **kwargs.

Do tej pory dowiedziałem się, że:

  • *args = lista argumentów-jako argumenty pozycyjne
  • **kwargs = słownik - którego klucze stają się oddzielnymi argumentami słów kluczowych, a wartości stają się wartościami tych argumentów.

Nie rozumiem, do jakiego zadania programistycznego byłoby to pomocne.

Może:

Myślę, aby wprowadzić listy i słowniki jako argumenty funkcji i jednocześnie jako symbole wieloznaczne, więc mogę przekazać dowolny argument?

Czy istnieje prosty przykład, aby wyjaśnić, jak *args i **kwargs są używane?

Również tutorial, który znalazłem, używał tylko " * " i nazwy zmiennej.

*args i **kwargs tylko placeholderami, czy używasz dokładnie *args i **kwargs w kodzie?

Author: Siddharth Satpathy, 2010-08-03

11 answers

Składnia to * i**. Nazwy *args i **kwargs są tylko umowne, ale nie ma twardego wymogu ich używania.

Użyjesz *args, gdy nie jesteś pewien, ile argumentów może zostać przekazanych do twojej funkcji, tzn. pozwala ona przekazać dowolną liczbę argumentów do twojej funkcji. Na przykład:

>>> def print_everything(*args):
        for count, thing in enumerate(args):
...         print( '{0}. {1}'.format(count, thing))
...
>>> print_everything('apple', 'banana', 'cabbage')
0. apple
1. banana
2. cabbage

Podobnie, **kwargs pozwala na obsługę nazwanych argumentów, których wcześniej nie zdefiniowałeś:

>>> def table_things(**kwargs):
...     for name, value in kwargs.items():
...         print( '{0} = {1}'.format(name, value))
...
>>> table_things(apple = 'fruit', cabbage = 'vegetable')
cabbage = vegetable
apple = fruit

Możesz użyć tych wraz z nazwanymi argumentami też. Argumenty jawne najpierw otrzymują wartości, a następnie Wszystko inne jest przekazywane do *args i **kwargs. Wymienione argumenty są pierwsze na liście. Na przykład:

def table_things(titlestring, **kwargs)

Można również użyć obu w tej samej definicji funkcji, ale {[6] } musi wystąpić przed **kwargs.

Można również używać składni * i ** podczas wywoływania funkcji. Na przykład:

>>> def print_three_things(a, b, c):
...     print( 'a = {0}, b = {1}, c = {2}'.format(a,b,c))
...
>>> mylist = ['aardvark', 'baboon', 'cat']
>>> print_three_things(*mylist)
a = aardvark, b = baboon, c = cat

Jak widać w tym przypadku pobiera listę (lub krotkę) elementów i rozpakowuje ją. Przez to dopasowuje je do argumentów w funkcji. Oczywiście, możesz mieć * zarówno w definicji funkcji, jak i w wywołaniu funkcji.

 1716
Author: Dave Webb,
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-03-23 15:15:58

Jednym z miejsc, gdzie użycie *args i **kwargs jest całkiem przydatne, jest podklasowanie.

class Foo(object):
    def __init__(self, value1, value2):
        # do something with the values
        print value1, value2

class MyFoo(Foo):
    def __init__(self, *args, **kwargs):
        # do something else, don't care about the args
        print 'myfoo'
        super(MyFoo, self).__init__(*args, **kwargs)

W ten sposób możesz rozszerzyć zachowanie klasy Foo, bez konieczności wiedzenia zbyt wiele o Foo. Może to być całkiem wygodne, jeśli programujesz do interfejsu API, który może się zmienić. MyFoo przekazuje wszystkie argumenty klasie Foo.

 495
Author: Mark van Lent,
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
2011-05-12 13:58:30

Oto przykład, który wykorzystuje 3 różne typy parametrów.

def func(required_arg, *args, **kwargs):
    # required_arg is a positional-only parameter.
    print required_arg

    # args is a tuple of positional arguments,
    # because the parameter name has * prepended.
    if args: # If args is not empty.
        print args

    # kwargs is a dictionary of keyword arguments,
    # because the parameter name has ** prepended.
    if kwargs: # If kwargs is not empty.
        print kwargs

>>> func()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: func() takes at least 1 argument (0 given)

>>> func("required argument")
required argument

>>> func("required argument", 1, 2, '3')
required argument
(1, 2, '3')

>>> func("required argument", 1, 2, '3', keyword1=4, keyword2="foo")
required argument
(1, 2, '3')
{'keyword2': 'foo', 'keyword1': 4}
 329
Author: Kit,
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
2013-11-02 00:50:10

Oto jedno z moich ulubionych miejsc do używania składni ** Jak w ostatnim przykładzie Dave ' a Webba:

mynum = 1000
mystr = 'Hello World!'
print("{mystr} New-style formatting is {mynum}x more fun!".format(**locals()))

Nie jestem pewien, czy jest to strasznie szybkie w porównaniu do używania samych nazw, ale jest o wiele łatwiejsze do wpisania!

 71
Author: Wayne Werner,
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
2020-10-13 07:30:16

Jednym z przypadków, w których *args i **kwargs są użyteczne jest pisanie funkcji wrappera (takich jak dekoratory), które muszą być w stanie zaakceptować dowolne argumenty, aby przejść do funkcji wrapperze. Na przykład prosty dekorator wypisujący argumenty i zwracaną wartość funkcji jest zawijany:

def mydecorator( f ):
   @functools.wraps( f )
   def wrapper( *args, **kwargs ):
      print "Calling f", args, kwargs
      v = f( *args, **kwargs )
      print "f returned", v
      return v
   return wrapper
 47
Author: jchl,
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-08-03 08:40:34

*args i * * kwargs to specjalne magiczne cechy Pythona. Pomyśl o funkcji, która może mieć nieznaną liczbę argumentów. Na przykład, z jakichkolwiek powodów, chcesz mieć funkcję, która sumuje nieznaną liczbę liczb (i nie chcesz używać wbudowanej funkcji sum). Więc piszesz tę funkcję:

def sumFunction(*args):
  result = 0
  for x in args:
    result += x
  return result

I użyj go jak: sumFunction(3,4,6,3,6,8,9).

**kwargs ma inną funkcję. Za pomocą * * kwargs możesz podać dowolne argumenty słów kluczowych funkcji i możesz uzyskać do nich dostęp jako dyktator.

def someFunction(**kwargs):
  if 'text' in kwargs:
    print kwargs['text']

Wywołanie funkcji (text= "foo") wyświetli foo.

 40
Author: Steven Mohr,
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-08-03 09:35:18

Wyobraź sobie, że masz funkcję, ale nie chcesz ograniczać liczby potrzebnych parametrów. Przykład:

>>> import operator
>>> def multiply(*args):
...  return reduce(operator.mul, args)

Następnie używasz tej funkcji jak:

>>> multiply(1,2,3)
6

or

>>> numbers = [1,2,3]
>>> multiply(*numbers)
6
 19
Author: Felix Kling,
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-08-03 08:40:07

Nazwy *args i **kwargs lub **kw są czysto umowne. Ułatwia nam to czytanie sobie nawzajem kodu

Jednym z przydatnych miejsc jest użycie modułu struct

struct.unpack() zwraca krotkę, podczas gdy struct.pack() używa zmiennej liczby argumentów. Podczas manipulowania danymi wygodnie jest przekazać krotkę struck.pack() np.

tuple_of_data = struct.unpack(format_str, data)
... manipulate the data
new_data = struct.pack(format_str, *tuple_of_data)

Bez tej zdolności byłabyś zmuszona napisać

new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...)

Co oznacza również, że jeśli formula_str zmienia się i wielkość krotka się zmienia, będę musiał wrócić i edytować tę naprawdę długą linię

 17
Author: John La Rooy,
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-08-03 08:39:07

Zauważ, że*args/* * kwargs jest częścią składni wywołującej funkcje, a tak naprawdę nie operatorem. Ma to szczególny efekt uboczny, na który wpadłem, czyli to, że nie można używać rozszerzenia *args z instrukcją print, ponieważ print nie jest funkcją.

To wydaje się rozsądne:

def myprint(*args):
    print *args

Niestety nie kompiluje się (błąd składni).

To zestawienie:

def myprint(*args):
    print args

Ale wyświetla argumenty jako krotkę, co nie jest tym, czego chcemy.

Oto rozwiązanie, które ustaliłem na:

def myprint(*args):
    for arg in args:
        print arg,
    print
 10
Author: yoyo,
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
2011-08-11 20:29:33

Te parametry są zwykle używane dla funkcji proxy, więc proxy może przekazać dowolny parametr wejściowy do funkcji docelowej.

def foo(bar=2, baz=5):
    print bar, baz

def proxy(x, *args, **kwargs): # reqire parameter x and accept any number of additional arguments
    print x
    foo(*args, **kwargs) # applies the "non-x" parameter to foo

proxy(23, 5, baz='foo') # calls foo with bar=5 and baz=foo
proxy(6)# calls foo with its default arguments
proxy(7, bar='asdas') # calls foo with bar='asdas' and leave baz default argument

Ale ponieważ te parametry ukrywają rzeczywiste nazwy parametrów, lepiej ich unikać.

 8
Author: Rudi,
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-08-03 08:41:27

Możesz rzucić okiem na python docs (docs.python.org w FAQ), ale dokładniej dla dobrego wyjaśnienia tajemnicza Panna args i mister kwargs (dzięki uprzejmości archive.org) (oryginalny, martwy link to Tutaj).

W skrócie, oba są używane, gdy używane są opcjonalne parametry funkcji lub metody. Jak mówi Dave, * args jest używany, gdy nie wiesz, ile argumentów może zostać przekazanych, a * * kwargs, gdy chcesz obsłużyć parametry określone przez nazwę i wartość jak w:

myfunction(myarg=1)
 3
Author: Yoni H,
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-03-22 17:38:57