Вопрос: * args и ** kwargs? [Дубликат]


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

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

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

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

Может быть:

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

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

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

Находятся *argsа также **kwargsпросто заполнители или вы используете точно *argsа также **kwargsв коде?


1178


источник


Ответы:


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

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


1450



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


439



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

276



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

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

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


63



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

38



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


35



Just imagine you have a function but you don't want to restrict the number of parameter it takes. Example:

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

Then you use this function like:

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

or

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

16



The names *args and **kwargs or **kw are purely by convention. It makes it easier for us to read each other's code

One place it is handy is when using the struct module

struct.unpack() returns a tuple whereas struct.pack() uses a variable number of arguments. When manipulating data it is convenient to be able to pass a tuple to struck.pack() eg.

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

without this ability you would be forced to write

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

which also means the if the format_str changes and the size of the tuple changes, I'll have to go back and edit that really long line


13



Note that *args/**kwargs is part of function-calling syntax, and not really an operator. This has a particular side effect that I ran into, which is that you can't use *args expansion with the print statement, since print is not a function.

This seems reasonable:

def myprint(*args):
    print *args

Unfortunately it doesn't compile (syntax error).

This compiles:

def myprint(*args):
    print args

But prints the arguments as a tuple, which isn't what we want.

This is the solution I settled on:

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

9



These parameters are typically used for proxy functions, so the proxy can pass any input parameter to the target function.

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

But since these parameters hide the actual parameter names, it is better to avoid them.


7