*args и **kwargs? [дубликат]


этот вопрос уже есть ответ здесь:

  • Что делают * * (двойная звезда/Звездочка) и * (звезда/Звездочка) для параметров? 18 ответов

так что у меня есть трудности с понятием *args и **kwargs.

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

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

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

может быть:

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

есть простой пример, чтобы объяснить, как *args и есть?

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

Are *args и **kwargs просто заполнители или вы используете именно *args и **kwargs в коде?

11 1217

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)