*args и **kwargs? [дубликат]
этот вопрос уже есть ответ здесь:
- Что делают * * (двойная звезда/Звездочка) и * (звезда/Звездочка) для параметров? 18 ответов
так что у меня есть трудности с понятием *args
и **kwargs
.
до сих пор я узнал, что:
-
*args
= список аргументов - как позиционные аргументы -
**kwargs
= словарь-ключи которого становятся отдельными аргументами ключевых слов, а значения становятся значениями этих аргументов.
Я не понимаю, для какой задачи программирования это было бы полезно.
может быть:
Я думаю, чтобы ввести списки и словари в качестве аргументов функции и в то же время в качестве подстановочного знака, так что я могу передать любой аргумент?
есть простой пример, чтобы объяснить, как *args
и есть?
также учебник, который я нашел, использовал только " * " и имя переменной.
Are *args
и **kwargs
просто заполнители или вы используете именно *args
и **kwargs
в коде?
11 ответов:
синтаксис
*
и**
. Имена*args
и**kwargs
только по соглашению, но нет жесткого требования, чтобы использовать их.можно использовать
*args
когда вы не уверены, сколько аргументов может быть передано в вашу функцию, т. е. это позволяет передавать произвольное количество аргументов в вашу функцию. Например:>>> 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
точно так же,
**kwargs
позволяет обрабатывать именованные аргументы, которые вы не определили в заранее:>>> 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
вы можете использовать их вместе с именованными аргументами тоже. Явные аргументы сначала получают значения, а затем все остальное передается в
*args
и**kwargs
. Именованные аргументы занимают первое место в списке. Например:def table_things(titlestring, **kwargs)
вы также можете использовать оба в том же определении функции, но
*args
до**kwargs
.вы также можете использовать
*
и**
синтаксис при вызове функции. Для пример:>>> 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
как вы можете видеть в этом случае он берет список (или кортеж) элементов и распаковывает его. Тем самым он сопоставляет их с аргументами в функции. Конечно, вы могли бы
*
как в определении функции, так и в вызове функции.
одно место, где использование
*args
и**kwargs
довольно полезно для подклассов.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)
таким образом, вы можете расширить поведение класса Foo, не зная слишком много о Foo. Это может быть довольно удобно, если вы программируете на API, который может измениться. MyFoo просто передает все аргументы классу Foo.
вот пример, который использует 3 различных типа параметров.
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}
вот одно из моих любимых мест, чтобы использовать
**
синтаксис, как в последнем примере Дэйва Уэбба:mynum = 1000 mystr = 'Hello World!' print "{mystr} New-style formatting is {mynum}x more fun!".format(**locals())
Я не уверен, что это ужасно быстро по сравнению с просто использованием самих имен, но это намного проще печатать!
один случай, когда *args и **kwargs полезны при написании функций-оболочек (таких как декораторы), которые должны иметь возможность принимать произвольные аргументы для передачи в обертываемую функцию. Например, простой декоратор, который печатает Аргументы и возвращает значение функции, которая обертывается:
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
* args и * * kwargs-это специальные магические функции Python. Подумайте о функции, которая может иметь неизвестное количество аргументов. Например, по каким-либо причинам вы хотите иметь функцию, которая суммирует неизвестное количество чисел (и вы не хотите использовать встроенную функцию sum). Поэтому вы пишете эту функцию:
def sumFunction(*args): result = 0 for x in args: result += x return result
и использовать его как: sumFunction(3,4,6,3,6,8,9).
* * kwargs имеет различную функцию. С помощью * * kwargs вы можете дать произвольные аргументы ключевого слова функция и вы можете получить к ним доступ в качестве словаря.
def someFunction(**kwargs): if 'text' in kwargs: print kwargs['text']
вызов someFunction (text="foo") выведет foo.
просто представьте, что у вас есть функция, но вы не хотите ограничивать количество параметров, которые она принимает. Пример:
>>> import operator >>> def multiply(*args): ... return reduce(operator.mul, args)
затем вы используете эту функцию, как:
>>> multiply(1,2,3) 6 or >>> numbers = [1,2,3] >>> multiply(*numbers) 6
имена
*args
и**kwargs
или**kw
чисто по Конвенции. Это делает его легче для нас, чтобы читать друг другу кододно место это удобно при использовании модуля struct
struct.unpack()
возвращает кортеж, тогда какstruct.pack()
использует переменное число аргументов. При манипулировании данными удобно иметь возможность передать Кортеж вstruck.pack()
например.tuple_of_data = struct.unpack(format_str, data) ... manipulate the data new_data = struct.pack(format_str, *tuple_of_data)
без этой способности вы были бы вынуждены писать
new_data = struct.pack(format_str, tuple_of_data[0], tuple_of_data[1], tuple_of_data[2],...)
что также означает, что если format_str изменится и размер кортежа изменится, мне придется вернуться и отредактировать эту действительно длинную строку
обратите внимание, что *args/**kwargs является частью синтаксиса вызова функций, а не оператором. Это имеет определенный побочный эффект, с которым я столкнулся, а именно, что вы не можете использовать расширение *args с оператором print, поскольку print не является функцией.
Это кажется разумным:
def myprint(*args): print *args
к сожалению, он не компилируется (синтаксическая ошибка).
Это компилирует:
def myprint(*args): print args
но печатает аргументы в виде кортежа, который не то, что мы хотеть.
Это решение я остановился на:
def myprint(*args): for arg in args: print arg, print
эти параметры обычно используются для прокси-функций, поэтому прокси может передавать любой входной параметр целевой функции.
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
но так как эти параметры скрывают фактические имена параметров, то лучше их избегать.
вы можете посмотреть на python docs (docs.python.org в FAQ), но более конкретно для хорошего объяснения таинственная Мисс Мистер args и kwargs (учтивость archive.org) (Оригинал, мертвая ссылка здесь).
в двух словах, оба используются, когда используются дополнительные параметры к функции или методу. Как говорит Дэйв, *args используется, когда вы не знаете, сколько аргументов может быть передано, и * * kwargs, когда вы хотите обрабатывать параметры указывается по имени и значению, как в:
myfunction(myarg=1)