Python函数定义中的*args和**kargs用法
在学习装饰器的时候,装饰函数(比如写一个计算函数运行时间的装饰函数)我们常常是不知道被装饰函数会传入多少参数的,因此在装饰函数中,常常会使用(*args, **kargs)的方式来定义内部函数。因此我们需要了解一下*args和**kargs在函数定义和函数使用方面的不同,他们两者被称为可变参数传入。
1、在函数定义时
可变参数传入最常见的使用,就是在函数的定义时,有些函数写出来我们并不确定函数使用者会传入多少的参数?就会使用*args和**kargs。
1.1、可变位置参数:*args
在函数定义中使用*args,当函数在使用的时候,无论用户传入多少的参数都会被args用元组来储存起来,函数内部可以对args任意操作来提取内部元素(也就是用户的输入参数),直接看例子。
def myfun(*args): print(type(args)) print("参数个数",len(args)) print("第一个参数:",args[0]) print("第二个参数:",args[1]) myfun(10, "我可以", [1,2])
执行结果:
可以看到我这里只输出了2个我传入的两个参数,如果我只传入1个参数,那么在代码的第5行将会报错,因为args元组中参数个数只有1个,无法提取args[1]。这就是函数定义时*args的用法,当然该用法也可以和指定参数一起使用,例如我在定义函数的时候def myfun(arg1, arg2, *args),那么这个时候传入参数的第一个参数会认为arg1,第二个参数时arg2,第三个即以后的传入的参数会被args当成元组组合。
1.2、可变关键字参数:**kargs
**kargs的用法和*args差不多,只不过kargs是采用字典的方式来收集传入的参数。可能会问kargs字典的键和值分别是什么呢?难道必须要求我们使用函数的时候传入一个字典进去?其实并不是,当我们使用函数时采用指定参数传入的时候,例如myfun(arg1=xxx, arg2=xxx)的时候,其中就会被收集成{arg1:xxx,arg2:xxx},看例子。
def myfun(**kargs): print(type(kargs)) print("参数个数",len(kargs)) print("字典具有那些键?",kargs.keys()) ## 打印kargs的所有项 for item in kargs.items(): print("item:",item) myfun(number=10, number2=['可以1','可以2'])
执行结果:
当然了,**kargs也可以和指定参数一样的使用,例如对上面这个例子稍微的改动下,我把myfun中指定number参数作为指定传入参数,再来看看输出。
def myfun(number, **kargs): print("参数number:",number) print(type(kargs)) print("参数个数",len(kargs)) print("字典具有那些键?",kargs.keys()) ## 打印kargs的所有项 for item in kargs.items(): print("item:",item) myfun(number=10, number2=['可以1','可以2'])
输出结果:
这个时候kargs只把number2收录到字典里了,number1被正常传入了。
2、在函数使用时
前面讲解了在函数定义的时候如何使用可变位置参数(可变关键字参数),这两个东西在函数使用的时候又有点不太一样。
2.1、可变位置参数:*args
在使用函数的时候,我们可以通过*元组(列表)的方式把元组(列表)中所有的元素传入进函数里。要注意args一定要是元组(列表),并且args的个数一定要和函数需要的参数个数一样多。看例子。
def myfun(arg1, arg2, arg3): print("参数arg1:",arg1) print("参数arg2:",arg2) print("参数arg3:",arg3) args = (1,2,3) myfun(*args)
输出结果:
其实这种用法只是一种很简洁的函数调用方式。
2.2、可变关键字参数:**kargs
同样的我们使用**kargs可以把一个字典传入函数,但是要注意的是这个字典的键(str)必须得和函数定义时的参数名对应。下面看例子。
def myfun(arg1, arg2, arg3): print("参数arg1:",arg1) print("参数arg2:",arg2) print("参数arg3:",arg3) kargs = {'arg1':1, 'arg2':2, 'arg3':"可以"} myfun(**kargs)
输出结果: