Использование * args и ** kwargs

Поэтому я испытываю трудности с концепцией *args и **kwargs.

До сих пор я узнал, что:

  • *args= список аргументов - как позиционные аргументы
  • **kwargs= dictionary - ключи которых становятся отдельными аргументами ключевого слова, а значения становятся значениями этих аргументов.

Я не понимаю, для какой задачи программирования это было бы полезно.

Может быть:

Я думаю, чтобы вводить списки и словари в качестве аргументов функции И в то же время, что и подстановочный знак, поэтому я могу передать ЛЮБОЙ аргумент?

Есть ли простой пример, чтобы объяснить, как используются *args и **kwargs?

Также в учебнике, который я нашел, использовалось только "*" и имя переменной.

Являются ли *args и **kwargs только заполнителями или вы используете точно *args и **kwargs в коде?

Ответы

Ответ 1

Синтаксис - это * и **. Имена *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

Как вы можете видеть, в этом случае он берет список (или кортеж) элементов и распаковывает его. Под этим он сопоставляет их с аргументами в функции. Конечно, вы можете иметь * как в определении функции, так и в вызове функции.

Ответ 2

Одно место, где использование *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

Вот пример, который использует 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}

Ответ 4

Здесь одно из моих любимых мест для использования синтаксиса **, как в последнем примере Dave Webb:

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

Я не уверен, что это ужасно быстро по сравнению с использованием самих имен, но это намного проще ввести!

Ответ 5

Один случай, когда * 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

Ответ 6

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

Ответ 7

Представьте, что у вас есть функция, но вы не хотите ограничивать количество параметров, которые она принимает. Пример:

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

Затем вы используете эту функцию, например:

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

or

>>> numbers = [1,2,3]
>>> multiply(*numbers)
6

Ответ 8

Имена *args и **kwargs или **kw носят чисто условный характер. Это упрощает чтение кода друг друга

Одно место удобно использовать при использовании структурного модуля

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

что также означает, что если изменяется формат_str и изменяется размер кортежа, мне придется вернуться и отредактировать эту действительно длинную строку

Ответ 9

Обратите внимание, что * args/** kwargs является частью синтаксиса для вызова функций и не является оператором. Это имеет специфический побочный эффект, с которым я столкнулся, что вы не можете использовать расширение args с оператором печати, поскольку печать не является функцией.

Это кажется разумным:

def myprint(*args):
    print *args

К сожалению, он не компилируется (синтаксическая ошибка).

Это компилируется:

def myprint(*args):
    print args

Но печатает аргументы в виде кортежа, чего мы не хотим.

Это решение, на котором я остановился:

def myprint(*args):
    for arg in args:
        print arg,
    print

Ответ 10

Эти параметры обычно используются для прокси-функций, поэтому прокси-сервер может передать любой входной параметр целевой функции.

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

Но поскольку эти параметры скрывают фактические имена параметров, лучше их избегать.

Ответ 11

Вы можете взглянуть на документы python (docs.python.org в FAQ), но более конкретно для хорошего объяснения таинственные мисс args и mister kwargs (любезно предоставлен archive.org) (оригинальная, мертвая ссылка здесь).

В двух словах оба используются, когда используются дополнительные параметры для функции или метода. Как говорит Дэйв, * args используется, когда вы не знаете, сколько аргументов может быть передано, и ** kwargs, когда вы хотите обрабатывать параметры, указанные по имени и значению, как в:

myfunction(myarg=1)