args - *args和**kwargs ?

  显示原文与译文双语对照的内容

这个问题已经有了如下答案:

所以我很难理解 *args 和 **kwargs.的概念

到目前为止,我已经了解到:

  • *args = 参数列表-as位置参数
  • **kwargs = 字典- 它的关键字成为独立关键字参数,值成为这些参数的值。

老实说我不理解,也不知道什么编程任务会有帮助。 ( 我肯定有,但我无法理解它。)

可能:

我想输入列表和字典作为函数的参数,同时作为一个通配符,所以我可以传递任何参数?

是否有一个简单的例子来解释如何使用 *args**kwargs

我运行的教程只使用了"*"和变量名。

*args**kwargs 只是一个占位符,还是在代码中使用 *args**kwargs

时间:

语法是 *** 。 名称 *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}

下面是我最喜欢使用 ** 语法的地方,如webb示例的Dave final:


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 special-magic python的特性。 请考虑可能有未知参数数目的函数。 例如出于任何原因,你都希望有一个函数来和未知数目的数字( 你不想使用内置求和函数) 。 所以你写这个函数:


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.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 是function-calling语法的一部分,而不是真正的操作符。 这有一个我遇到的特殊副作用,那就是你不能在print语句中使用 *args 扩展,因为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

但是由于这些参数隐藏了实际参数名,所以最好避免它们。

...