关于方法的参数:位置参数—》默认参数—》可变参数—》关键字参数 | 可变关键字参数
–认真学习了一下python方法参数的用法,大概总结了以下内容,应该还是比较全面的–
定义参数:
参数的定义顺序是:位置参数---》默认参数---》可变参数---》关键字参数 | 可变关键字参数
def 方法名(位置参数,默认参数 = 默认值,可变参数(*args) , 关键字参数(可以有关键字的默认
值)| 可变关键字参数(**kwargs) )
eg:
def test(arg1 , arg2 , arg3 = 5 , *args , arg4name = 6 , arg5name ,**kwargs):
print('arg1:',arg1) #位置参数1
print('arg2:',arg2) #位置参数2
print('arg3:',arg3) #默认参数
print('args:',args) #可变参数,结果是一个元组
print('arg4name::',arg4name) #关键字参数,带有默认值
print('arg5name:',arg5name) #关键字参数,不带默认值
print('kwargs:',kwargs) #可变关键字参数,结果是一个结合
#test1 全部正常赋值
test(1,2,3,4,5,arg4name=5,arg5name=6,arg5=8,arg6=9)
#结果--》
arg1: 1
arg2: 2
arg3: 3
args: (4, 5)
arg4name:: 5
arg5name: 6
kwargs: {'arg5': 8, 'arg6': 9}
解释:首先对于直接赋值的参数,方法默认按顺序占位,比如1占位arg1,2占位arg2,3占位arg3,4和5
默认占位args可变参数,此时无论写多少都会让args照单全收,再后面就是按照关键字赋值的形式进
行赋值,这个区间(args后面的关键字参数区间)就可以任意随便的赋值,没有先后之分,关键在每
个键值要有值对应
#test2 最少参数
test(1,2,arg5name=3)
#结果--》
arg1: 1
arg2: 2
arg3: 5
args: ()
arg4name:: 6
arg5name: 3
kwargs: {}
解释:对于未知参数,必须全部赋值(任何形式赋值均可);对于关键字参数,如果关键字参数没有
默认值,那么也必须赋值
结论:所以当函数已经有位置参数和未赋值的关键字参数,那么调用方法的时候,必须为他们传值
#test3 小小的升华
test(1,arg2=2,arg3=4,arg4=6,arg7=8,arg4name=9,arg5name=10,arg8=11)
#结果--》
arg1: 1
arg2: 2
arg3: 4
args: ()
arg4name:: 9
arg5name: 10
kwargs: {'arg4': 6, 'arg7': 8, 'arg8': 11}
解释:显然这儿就会有疑问了,为什么arg2,arg3可以用形似关键字的模式传值呢?其实,这个只不过
是传值而已,它本身还是位置参数或者默认值参数。但是一定要记住,这种形似关键字参数 参数名
==值 和关键字参数赋值 都必须放到 占位的位置参数后面,简言之,调用方法的时候,带有参数名
赋值的必须写到单独一个赋值的后面
为什么会这样呢?????其实吧,还是之前提到的占位的问题,单独一个数的赋值,会直接按照位
置占位,如果都是 参数名 == 值的形式,那就无所谓顺序了,随便写到哪个位置都可以。但是该赋
值的千万要赋值(位置参数,未赋值的关键字参数)。
所以,此时你会不会有一个想法:
test(arg4=6,arg7=8,arg5name=10,arg8=11,arg1 =0,arg2=2,arg3=4,arg4name=9) 可以吗?
当然可以,没有占位就可以关键字形式的无序赋值
#test4 *args,**kwargs的理解
test(1,2,3,4,5,5,6,7,8,arg4name=7,arg5name=10,arg6name=11,arg7name=10)
结果--》
arg1: 1
arg2: 2
arg3: 3
args: (4, 5, 5, 6, 7, 8)
arg4name:: 7
arg5name: 10
kwargs: {'arg6name': 11, 'arg7name': 10}
解释:(1)有没有发现,凡是关键字参数------必须用 参数名=参数值 的形式赋值;
(2)当传入的参数占位位置参数和默认参数以后,多余的参数会保存到元组args中。
当传入的键值对参数( 参数名=参数值)除了参数必要的值以外,均会保存到字典kwargs中。
------->其实,可变参数args以及前面的位置参数,默认参数 ,方法是将他们放到一个元组中进
行操作的,args只是一个子集(理解即可)
------->关键字参数,方法是将他们放到一个字典中进行操作处理的,kwargs也只是一个子集
(理解即可)
所以也可以写成这样的形式:
test(*(1,2,3,4,5,5,6,7,8),**{'arg4name':7,'arg5name':10,'arg6name':11,'arg8name'=10})
结果:--》
arg1: 1
arg2: 2
arg3: 3
args: (4, 5, 5, 6, 7, 8)
arg4name:: 7
arg5name: 10
kwargs: {'arg6name': 11, 'arg8name': 10}
同样注意:关键字参数必须放到元组参数后面
当然还有一种情况:test(**{'arg1':1,'arg2':2,'arg4name': 7, 'arg5name': 10,
'arg6name': 11, 'arg8name' : 10})
结果:
arg1: 1
arg2: 2
arg3: 5
args: ()
arg4name:: 7
arg5name: 10
kwargs: {'arg6name': 11, 'arg8name': 10}
这样也是可以的。这个就完全是用关键字参数进行赋值的,如果有元组参数写入,必须写到关
键字参数前面
#test5 关键字默认参数-----》很受欢迎
形似列表的sort方法,内置函数sorted()方法,他们都有一个共同的key的关键字参数,(注意了:我
们使用ctr+鼠标左键 找到的他们的函数方法,并不是程序真正调用的底层,应该只是帮助理解用的)
经过测试,key值在底层的代码中,肯定是利用的关键字默认值参数,而不是默认值参数
****这个用法非常普遍,也非常的实用,相比较默认值参数来说,更好用点吧。一般如果参数默认值
为一个方法,最好用关键字默认参数,用多了,就感觉到了。
#################################################################################
**错误案例:**
error1: 代表性的缺少参数赋值
test(1)
解释:很显然,首先1占位arg1参数,但是还有位置参数arg2和未赋值的关键字参数arg5name没
有赋值,报错
error2: 单个赋值数写到了键值对赋值的后面
test(1,arg4name = 8,arg5name = 9,3)
解释:这是一个写出来pycharm软件就会报错的例子,我们本来的意思是让1占位arg1,3占位arg2,
但是这样的写法,python是不认同的,记住:带有形似关键字赋值的表达式必须写在只有一个值
的后面(1,3必须写在arg4name = 8,arg5name = 9的前面)