Python 中 *args 和 **kwargs 的使用 技术背景在 Python 编程中,有时候我们不确定函数会接收到多少个参数,或者需要处理一些未预先定义的命名参数。*args
和 **kwargs
就是为了解决这些问题而设计的特殊语法。
实现步骤 使用 *args*args
允许你将任意数量的位置参数传递给函数。这些参数会被打包成一个元组。示例代码如下:
1 2 3 4 5 def print_everything (*args ): for count, thing in enumerate (args): print ('{0}. {1}' .format (count, thing)) print_everything('apple' , 'banana' , 'cabbage' )
PYTHON
使用 **kwargs**kwargs
允许你处理未预先定义的命名参数,这些参数会被打包成一个字典。示例代码如下:
1 2 3 4 5 def table_things (**kwargs ): for name, value in kwargs.items(): print ('{0} = {1}' .format (name, value)) table_things(apple='fruit' , cabbage='vegetable' )
PYTHON
结合使用命名参数、*args 和 **kwargs你可以在函数定义中同时使用命名参数、*args
和 **kwargs
,但 *args
必须位于 **kwargs
之前。示例代码如下:
1 2 3 4 5 6 def table_things (titlestring, *args, **kwargs ): print (titlestring) if args: print (args) if kwargs: print (kwargs)
PYTHON
在函数调用时使用 * 和 ** 语法你也可以在调用函数时使用 *
和 **
语法来解包参数。示例代码如下:
1 2 3 4 5 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)
PYTHON
最佳实践 子类化*args
和 **kwargs
在子类化时非常有用,可以在不了解父类具体参数的情况下扩展其行为。示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 class Foo (object ): def __init__ (self, value1, value2 ): print (value1, value2)class MyFoo (Foo ): def __init__ (self, *args, **kwargs ): print ('myfoo' ) super (MyFoo, self ).__init__(*args, **kwargs)
PYTHON
包装函数在编写包装函数(如装饰器)时,*args
和 **kwargs
可以接受任意参数并传递给被包装的函数。示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 import functoolsdef 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
PYTHON
常见问题 无法使用 *args 展开与 print 语句一起使用在 Python 2 中,print
是语句而不是函数,因此无法使用 *args
展开。可以通过遍历参数并逐个打印来解决。示例代码如下:
1 2 3 4 def myprint (*args ): for arg in args: print (arg, end=" " ) print ()
PYTHON
参数隐藏问题由于 *args
和 **kwargs
会隐藏实际的参数名称,可能会降低代码的可读性。因此,在可以确定参数的情况下,应尽量避免使用它们。