所以我对
*args
和**kwargs
的概念感到困难。到目前为止,我了解到:
*args
=列表自变量-作为位置自变量**kwargs
=字典-其键成为单独的关键字自变量,值成为这些自变量的值。我不明白这是什么编程任务会有所帮助。
也许:
我想输入列表和字典作为函数的参数,并与通配符同时输入,所以我可以传递ANY参数吗?
是否有一个简单的示例来说明如何使用
*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
如您所见,在这种情况下,它将获取项目列表(或元组)并解压缩。这样,就可以将它们与函数中的参数匹配。当然,在函数定义和函数调用中都可以有一个
*
。评论
您如何在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
评论
一旦掌握了这些知识,就永远不会想念它们(尤其是如果您不得不处理PHP的func _ * _ args())。该文档位于docs.python.org/faq/programming.html#id13,顺便说一句。
实际上,可以将这2个参数格式添加到任何函数声明中,只要它们是最后2个即可。请注意顺序:显式args,然后是* args,然后是* kwargs。例如def foo(arg1,arg2,* args,** kwargs):...
准确解释。此关键字的数据类型是了解其操作的最关键。
(如果您使用的是Javascript,则存在类似的arguments数组)