我发现,好多学习python的同学都遇到非常费解的地方,那就是 *args 和 **kwargs 这两个魔法变量,那么这两个变量具体是怎么用的呢,它魔法在什么地方呢?
* 和 **
其实, 并不是必须写成 *args 和 **kwargs,真正在参数传递时起作用的,只有变量前面的 *(星号)。你也可以写成 *params 和 **kv_params。也就是说,*args 和 **kwargs 只是一种通俗的写法,但不是必须的。
* 用于传入的多个参数将按照元组形式存储,是一个元组。
** 用于参数前则表示传入的(多个)参数将按照字典的形式存储,是一个字典。
下面,我们通过代码的形式来一一介绍它们具体是怎么使用的!
Talk is cheap,Show you the code
*args 的用法
*args 和 **kwargs 主要在函数定义的时候使用。 而 *args 是用来发送一个非键值对的可变数量的参数列表给一个函数。
def test_args(normal_arg, *args):
print("正常的参数:", normal_arg)
print("*args:", args, "类型:", type(args))
for arg in args:
print("通过*args传递的参数:", arg)
test_args('python', 'java', 'c/c++', 'go')
上面的代码执行结果如下:
*args: ('java', 'c/c++', 'go') 类型: <class 'tuple'>
通过*args传递的参数: java
通过*args传递的参数: c/c++
通过*args传递的参数: go
可以发现,看起来test_args函数只接收两个参数,可实际上我们向test_args函数传递了四个参数,魔法之处就在于 *args,实际上是 *args 把多个参数组装成了一个元组传递给了test_args函数,可以看出,上面程序输出也是如此。
**kwargs 的用法
**kwargs 允许你将不定长度的键值对, 作为参数传递给一个函数。如果你想要在一个函数里处理一些带名字的参数, 你就要使用 **kwargs 了。下面是一个例子:
def test_kwargs(**kwargs):
print("**kwargs:", kwargs, "类型:", type(kwargs))
for key, value in kwargs.items():
print("{0} == {1}".format(key, value))
test_kwargs(name="tom", age="3")
上面的代码执行结果如下:
**kwargs: {'name': 'tom', 'age': '3'} 类型: <class 'dict'>
name == tom
age == 3
**kwargs 把多个参数组装成了一个字典传递给了test_kwargs函数,到这,你可以知道怎样在一个函数里, 处理了一个键值对参数了。
使用 *args 和 **kwargs 来调用函数
那现在我们将看到怎样使用 *args和 **kwargs 来调用一个函数。假设,你有这样一个的函数:
def test_args_kwargs(arg1, arg2, arg3):
print("arg1:", arg1)
print("arg2:", arg2)
print("arg3:", arg3)
你可以使用 *args 或 **kwargs来给这个函数传递参数:
# 使用 *args方式
args = ("python", "java", "go")
test_args_kwargs(*args)
# 使用 **kwargs方式
kwargs = {"arg2": "java", "arg3": "go", "arg1": "python"}
test_args_kwargs(**kwargs)
上述两种调用方式会得到一样的输出,其实 * 和 **kwargs 是对元组 和 字典的解引用。
总结
只要一个函数在定义时使用了*args 和 **kwargs 这两个关键字作为参数,你可以肆无忌惮的将不定数量、不定类型的参数传递给这个函数,哈哈哈,是不是无敌了。
注意:那么如果你想在函数里同时使用所有这三种参数, 顺序是这样的:your_func(arg, *args, **kwargs) 不能将 **kwargs 置于 *args之前,否则将产生错误。
最后,感谢女朋友在工作和生活中的包容、理解与支持 !