所以我对*args**kwargs的概念感到困难。

到目前为止,我了解到:



*args =列表自变量-作为位置自变量

**kwargs =字典-其键成为单独的关键字自变量,值成为这些自变量的值。

我不明白这是什么编程任务会有所帮助。

也许:

我想输入列表和字典作为函数的参数,并与通配符同时输入,所以我可以传递ANY参数吗?

是否有一个简单的示例来说明如何使用*args**kwargs

我发现的教程仅使用“ *”和变量名。

*args**kwargs只是占位符还是在代码中使用了*args**kwargs

评论

一旦掌握了这些知识,就永远不会想念它们(尤其是如果您不得不处理PHP的func _ * _ args())。

该文档位于docs.python.org/faq/programming.html#id13,顺便说一句。

实际上,可以将这2个参数格式添加到任何函数声明中,只要它们是最后2个即可。请注意顺序:显式args,然后是* args,然后是* kwargs。例如def foo(arg1,arg2,* args,** kwargs):...

准确解释。此关键字的数据类型是了解其操作的最关键。

(如果您使用的是Javascript,则存在类似的arguments数组)

#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


如您所见,在这种情况下,它将获取项目列表(或元组)并解压缩。这样,就可以将它们与函数中的参数匹配。当然,在函数定义和函数调用中都可以有一个*

评论


您如何在python帮助/文档中查找此内容?

– Alex
2014年3月28日在21:57

@Alex:在这里

– Mr_and_Mrs_D
14年7月29日在18:00

像在function_call(arg1,arg2,* expanded_list_args,arg4,arg5)中一样,似乎无法扩展在函数调用中间作为位置参数传递的列表。我相信在扩展列表之后只能加上关键字参数。有办法解决这个问题吗?

– mlh3789
2014-09-25 15:59

@ mlh3789是的,这仅适用于python3。但是实际上有点奇怪:这种方法适用于赋值:a,b,* c,d,e = 1、2、3、4、5、6将c赋给[3,4]。有点混乱

–克里斯蒂安·蒂斯默(Christian Tismer)
14-10-6在11:11



在上面的示例中,mylist就像JS中的数组。我们正常的print_three_things方法需要3个参数。将*注释传递给print_three_things(* mylist),或多或少类似于ES6中的扩展运算符。让我知道我的考虑是否正确?谢谢

–原始Kallio
17-6-22在3:12



#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类。

评论


仅当您已经了解*和**时,此答案才真正有意义。

–斯科特·泰斯勒(Scott Tesler)
13年2月24日在21:57

我不明白如果您的API发生更改,则仍然必须更改实例化子类的所有位置。而且,如果您要更改所有这些位置,则最好固定子类的签名,而不要无故与args和kwargs一起被黑。您不需要Foo知识的推理是没有意义的,因为一旦Foo构造函数的set签名更改,您所有的MyFoo实例化调用也将必须更改。这需要了解Foo及其构造函数所需的参数。

–佐兰·帕夫洛维奇(Zoran Pavlovic)
13年5月28日在15:20

@ZoranPavlovic可以使用此示例的情况是,您要为现有产品提供附加组件,并且想要覆盖/扩展某些功能。通过使用* args和** kwargs,如果基础产品发生更改,此附加组件将继续运行。但是,实例化MyFoo发生在附加组件之外。这有意义吗? (话虽如此:装饰器是何时可以使用* args和** kwargs的更好示例。)

–马克·范·伦特
13年5月28日在20:28



如何将其扩展为子类的特定参数?

– Hanan Shteingart
2014年8月12日19:01

@kavinyao:您显然不了解Python,也没有测试您编写的内容。 value2作为args中的第一个元素,因此也不例外。

–马可·苏拉(Marco Sulla)
19/12/24在18:27



#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的最后一个示例中一样:输入!

评论


嘿,这家伙在凉爽之前发明了Python 3.6 f弦

–猫
17年5月23日在19:20

@cat请解释一下?您指的是什么?即使在Python 2中,格式化方法也不存在吗?

–达巴达巴
17年9月28日在8:56

@dabadaba f字符串,而不是格式字符串(例如f'{mystr}新型格式{mynum}倍有趣!')

–Wayne Werner
17-9-28在18:32



@dabadaba恭喜您成为今天的幸运10k之一

–Wayne Werner
17年9月29日在13:45

@dabadaba参见python.org/dev/peps/pep-0498

–猫
17年9月29日在16:17

#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模块时

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更改并且元组的大小更改,我将不得不返回并编辑那条很长的行

#9 楼

请注意,* args / ** kwargs是函数调用语法的一部分,而不是真正的运算符。我遇到了一个特别的副作用,就是您不能在print语句中使用* args扩展,因为print不是一个函数。
def myprint(*args):
    print *args


很遗憾,它无法编译(语法错误)。

此编译器:

def myprint(*args):
    print args


但是将参数打印为元组,这不是我们想要的。

这是我确定的解决方案:

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


评论


当然总是从__future__导入print_function :)

–pfctdayelise
2011年11月21日,下午5:12

print是Python3中的函数:) docs.python.org/3.0/whatsnew/3.0.html

–sk8asd123
13年8月30日在14:25

#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(常见问题解答中的docs.python.org),但更具体地讲,是一个很好的解释,神秘的args和miser kwargs小姐(由archive.org提供)(原始的无效链接在这里)。

简而言之,当使用函数或方法的可选参数时,两者都使用。
如Dave所说,当您不知道可以传递多少个参数时,将使用* args;而当您要处理由名称和值指定的参数时,则使用** kargs,如:

myfunction(myarg=1)


评论



“这里是一个链接,也是其他人所说的”不是一个有用的答案。关于这个答案实际上唯一说的唯一一句话就是暗示** kwargs必须使用命名参数,这是错误的。它只需要处理任意命名的参数。

– underscore_d
17年6月10日在10:46