日常工作or看源码的过程中经常看到诸如此类的python函数,可传入任意参数
def func(*args,**kwargs):
不要说新手,即使是老手估计也是用的多,但是能说清楚各种情况各种用法的估计也少。故笔者尝试用本文说清除各种情况。
基础部分
测试代码如下
a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
b = {'a': 1, 'b': 2}
print(*a)
print(*b)
有结果:
0 1 2 3 4 5 6 7 8 9
a b
可以看出*号的作用,将list or tuple解析为独立的若干个对象,将dict的key值解析为 a b两个独立对象
print(**b)
直接解包会报错,但是在函数中可以使用,下文会说明。
补充函数:
def func(*args,**kwargs):
print(f'args是{args},类型是{type(args)}')
print(f'kwargs是{kwargs},类型是{type(kwargs)}')
此函数的基础用法
func(1,2,3,a=4,b=5,c=6)
按此格式,即1,2,3必须在a = 1前面,可以接受任意多的参数
运行结果:
args是(1, 2, 3),类型是<class 'tuple'>
kwargs是{'a': 4, 'b': 5, 'c': 6},类型是<class 'dict'>
进阶
那么,我们将list(tuple),和dict以各种形式传进去,会发生什么呢?
情况一
func(a,b)
结果:
args是([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], {'a': 1, 'b': 2}),类型是<class 'tuple'>
kwargs是{},类型是<class 'dict'>
可以看到,两个对象都被封装进了一个tuple,也就是说,这样不论传参多少个,都不会被封进*args所代表的tuple
情况二
func(*b,*a)
结果:
args是('a', 'b', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9),类型是<class 'tuple'>
kwargs是{},类型是<class 'dict'>
*号将b和a解析为多个对象,然后都传入,还是被封装进了一个tuple
友情提示:如果觉得写的不错麻烦给个赞!QAQ
情况三
func(a,*b)
答案:
args是([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], 'a', 'b'),类型是<class 'tuple'>
kwargs是{},类型是<class 'dict'>
*b被解析为’a’,'b’两个对象,a是一个对象,故三个对象被封装进tuple
情况四
func(**b)
这里情况比较特殊,对于dict,一般的**都会报错,但是传参的时候不会。
结果:
args是(),类型是<class 'tuple'>
kwargs是{'a': 1, 'b': 2},类型是<class 'dict'>
可以看到,tuple是空的,b被识别为kwargs的输入,类别为dict
于是可以这样理解
func(**b)等价于func(a=1,b=2)
func(a=1,b=2)
args是(),类型是<class 'tuple'>
kwargs是{'a': 1, 'b': 2},类型是<class 'dict'>
情况五
func(*b,**b)
结果:
args是('a', 'b'),类型是<class 'tuple'>
kwargs是{'a': 1, 'b': 2},类型是<class 'dict'>
*b解析传入为’a’,'b’两个对象,**b同上。
练习
下面函数能否正常打印?如果能,结果是什么?如果不能,原因错在哪,应该如何修改?
1.func(*a,**b)
2.func(**b,a)
3.func(**a)
4.func(**b, c = 3, d= 4)
5.func(*a,a)
6.func(*b,a,b,c = 3, **b, d =4 )
欢迎在评论区留下你的答案