*args
和 **kwargs
的用法猛滴打开博客,发现实在有段时间没更新了。又刚好用到了**kwargs 。
遂想起了许久之前总结的这篇博客,夸张点说也算是自己的一个呕心沥血之作吧。
相信不少同学在看大神的程序时,总会看见 *args, **kwargs 这样的写法,但你知道这种写法的含义是什么吗?
对于大部分Python初学者而言,*args
和 ``kwargs` 这两个魔法变量需要花费大量时间来解释。别被这些语句所绊倒。其实这些并不是什么超级特殊的参数,也并不奇特,只是编程人员约定的变量名字,args 是 arguments 的缩写,表示位置参数;kwargs 是 keyword arguments 的缩写,表示关键字参数。 接下来我们就来一起了解他们的用法**,以及在什么情况下使用?·
首先你要明白的是:
*args
和 **kwargs
,只有前面的 * (星号)才是必须的。现在我们再来看 *args 与 **kwargs 的区别,两者都是 python 中可变的参数
*args 表示任何多个无名参数, 他本质上是一个 tuple
** kwargs 表示关键字参数, 它本质上是一个 dict
同时使用时必须要求 *args 参数列要在** kwargs 前面 【因为位置参数在关键字参数的前面。】
*
常常与乘法运算,C语言中的指针 有关,但在python中,则是 splat
运算符的 两倍。且 splat运算符需要更强大的类比
a = [1,2,3]
b = [*a,4,5,6]
b
# ----------------- 输出结果 -----------------
# [1, 2, 3, 4, 5, 6]
# ----------------- 总结 -----------------
# 将a的内容移入(解包)到新列表b中。
* args 和 ** args 主要用于函数定义,你可以将不定数量的参数传递给一个函数。
这里不定的意思是: 预先并不知道,函数使用者会传递多少个参数给你,所在在这个场景下使用这两个关键字。 * args 是用来发送一个 非键值 的可变数量的参数列表给一个函数。
def test_var_args(f_arg, *argv):
print("first normal arg:",f_arg)
for arg in argv:
print("another arg through *argv:",arg)
test_var_args('yasoob','python','eggs','test')
输出结果:
first normal arg: yasoob
another arg through *argv: python
another arg through *argv: eggs
another arg through *argv: test
def print_func(*args):
print(type(args))
print(args)
print_func(1,2,'python希望社',[])
输出结果
<class 'tuple'>
(1, 2, 'python希望社', [])
def print_func(x,y,*args):
print(type(x))
print(x)
print(y)
print(type(args))
print(args)
print_func(1,2,'python希望社',[])
输出结果
<class 'int'>
1
2
<class 'tuple'>
('python希望社', [])
def print_func(*args,x,y):
print(type(x))
print(x)
print(y)
print(type(args))
print(args)
输出结果
TypeError: print_func() missing 2 required keyword-only arguments: 'x' and 'y'
可以看出,打印函数 print_func
找不到关键词参数 x
和 y
所以若 *args
不是在最后,则需要在参数传入时,明确定义 *args
后面的变量参数名,如下:
# 改正的代码
def print_func(*args,x,y):
print(type(x))
print(x)
print(y)
print(type(args))
print(args)
print_func(1,2,'python希望社',[],x='x',y='y')
输出结果
<class 'str'>
x
y
<class 'tuple'>
(1, 2, 'python希望社', [])
*args
放在中间进一步滴我们可以考虑 将*args
放在中间,结果如何。就让大家自己来动手看看吧?
**kwargs
允许你将不定长度的 【键值对 key-value 】,作为参数传递给一个函数。如果你想要在一个函数里处理带名字的参数,你应该使用**kwargs
def print_func(**kwargs):
print(type(kwargs))
print(kwargs)
print_func(1, 2, 'python希望社', [])
输出结果:
TypeError: print_func() takes 0 positional arguments but 4 were given
直接报错了,大致意思是需要给出四个参数! 改正:
def print_func(**kwargs):
print(type(kwargs))
print(kwargs)
print_func(a=1, b=2, c='呵呵哒', d=[])
输出结果:
<class 'dict'>
{'a': 1, 'b': 2, 'c': '呵呵哒', 'd': []}
总结: 入参时,多添加了关键词。可以看到打印时,kwargs本身是字典类型,将传入的参数以字典形式呈现出来。
def greet_me(**kwargs):
for key, value in kwargs.items():
print("{0} == {1}".format(key, value))
greet_me(name="yasoob")
输出结果
name == yasoob
现在你可以看出我们怎样在一个函数里,处理了一个【键值对 key-value 】参数了
args
,*args
和 **kwargs
来调用函数arg,*args,**kwargs
,三者是可以组合使用的,但是组合使用需要遵循一定的语法规则,即顺序为王。
需要按照:
arg,*args,**kwargs
作为函数参数的顺序。
def print_func(x, *args, **kwargs):
print(x)
print(args)
print(kwargs)
print_func(1, 2, 3, 4, y=1, a=2, b=3, c=4)
输出结果
1
(2, 3, 4)
{'y': 1, 'a': 2, 'b': 3, 'c': 4}
那现在我们将看到怎样使用*args
和 **kwargs
来调用一个函数。假设,你有这样一个小函数
def test_args_kwargs(arg1,arg2,arg3):
print("arg1:",arg1)
print("arg2:",arg2)
print("arg3:",arg3)
你可以使用 *args
和 **kwargs
来给这个小函数传递参数。 下面是怎样做得:
# 首先你可以使用 *args
args = ("two",3,5)
test_args_kwargs(*args)
#-------- 得到输出结果如下所示:----------------------
# arg1: two
# arg2: 3
# arg3: 5
# ---------------------------------------------------
# 现在使用 **kwargs
kwargs = {"arg3": 3,"arg2":"two","arg1":5}
test_args_kwargs(**kwargs)
#-------- 得到输出结果如下所示:----------------------
# arg1: 5
# arg2: two
# arg3: 3
# ---------------------------------------------------