参数中的星号
参数中的星号
1 参数中的 *args 和 **kwargs
在了解 *args 和 **kwargs 的作用之前,首先要理解 * 和 ** 在 Python 中的使用。* 和 ** 主要有三方面的用途:
- 对可迭代对象进行拆分
- 可变变量的赋值
- 函数的可选参数标志
1.1 对可迭代对象进行拆分
print(*(1, 2, 3)) # 1 2 3
print(*{'a': 1, 'b': 2, 'c': 3}) # a b c 拆解字典时只拆解key
print({**{'a': 1, 'b': 2, 'c': 3}})# {'a': 1, 'b': 2, 'c': 3}对key和value都进行了拆解
所以对于 *args 和 **kwargs,args 就是可迭代对象,而 kwargs 就是字典
1.2 可变变量的赋值
对于一个可迭代对象 l,如果想把第一个元素赋值给变量 a,最后一个元素赋值给 c,而把剩下的元素统统赋值给变量 b,第一想法可能是用切片,这样需要写三行代码,太麻烦,并且对 unsubscriptable 的对象是不适用的(比如集合),所以用 * 可以解决这个问题。
a, *b, c = {1, 2, 3, 4, 5, 6}
#a = 1, b = [2, 3, 4, 5], c = 6
1.3 函数的可选参数标志
理解了前面两点后,这一点就是把前两点给结合起来运用。如果是单星号 * 标记的就是可选的位置参数(positional arguments),如果是双星号 ** 标记的就是可选的关键词参数(keyword arguments)
def function(a, *args, **kwargs):
print(a, args, kwargs)
function(1, 2, 3, c=4, d=5) # 输出1 (2, 3) {'c': 4, 'd': 5}
2 参数中的 / 和 *
先要搞清楚必选参数,默认参数,可变长度的位置参数,可变长度的关键字参数,位置参数和关键字参数分别表示的是什么
def function(a, b, c, d=4, *args, **kwargs):
pass
在上面这个例子中,a,b,c 是必选参数,d 是默认参数,args 和 kwargs 分别是可变长度的位置参数和可变长度的关键字参数,有了第一节的讲解这个应该很容易理解。当然也可以改变默认参数的值,比如function(1, 2, 3, d=5)
那么此时 d 的值就是 5 而不再是 4。
args 和 kwargs 我个人觉得还是尽量少用,如果函数中有这两个参数,那么必须通过调用才知道传进来的是什么内容,并且同时有这4种参数时,顺序规则比较复杂(想要了Python中默认的函数参数顺序的可以参考知乎上这篇文章的第五节内容或PEP 3102 – Keyword-Only Arguments),因此接下来就不再考虑这两个参数。
位置参数和关键字参数是函数调用时候的概念,而上面四种参数是函数定义时候的概念。
def function(a, b, c, d=4):
print(a, b, c, d)
function(1, 2, c=3, d=5) # 输出 1 2 3 5
此时 1 和 2 是位置参数,3 和 5 是关键字参数,默认参数不一定是关键字参数,比如function(0, 1, 2, 3)
此时就是通过位置参数的方式传递给 d。
Python 规定位置参数在左,关键字参数在右,比如function(1, b=2, 3)
这就会报错,位置参数必须严格在关键字参数的左边。
Python3.8 之后函数参数中允许出现 / 和 * 号,/ 用来指明某些函数形参必须使用位置参数的形式,对于单独出现在参数中的 * 参数,则表示,* 后面的参数必须为关键字参数的形式,比如:
def function(a, b, /, c, *, d, e)
pass
function(1, 2, 3, d=4, e=5)
function(1, 2, c=3, d=4, e=5)
a 和 b 只能用位置参数的形式,c 既可以用位置参数的形式又可以用关键字参数的形式,d 和 e 只能用关键字参数的形式。
Reference
【Python】函数中的*args和**kwargs是个什么东西?