Użycie * args i * * kwargs [duplikat]
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.
Są *args
i **kwargs
tylko placeholderami, czy używasz dokładnie *args
i **kwargs
w kodzie?
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.
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.
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}
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!
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
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.
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
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ę
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
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ć.
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)
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