这是听了Egon老师林海峰老师课的笔记
一、什么是可变长参数
可变长指的是实参值的个数不固定 而实参有按位置和按关键字两种形式定义,
针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs
下面我将为大家依依介绍它们的存在:
补充:
#1、位置参数:按照从左到右的顺序定义的参数
位置形参:必选参数
位置实参:按照位置给形参传值
def func(a,b):
print(a,b)
func(1,2)# -->1,2
#2、关键字参数:按照key=value的形式定义的实参
无需按照位置为形参传值
注意的问题:
1. 关键字实参必须在位置实参右面
2. 对同一个形参不能重复传值
def func(a,b):
print(a,b)
func(b=1,a=2)# -->2,1
#3、默认参数:形参在定义时就已经为其赋值
可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参)
注意的问题:
1. 只在定义时赋值一次
2. 默认参数的定义应该在位置形参右面
3. 默认参数通常应该定义成不可变类型
def func(a=1,b=2):
print(a,b)
func()# -->1,2
二、关于*args参数的那点事:
# 可变长度的位置参数
# *形参名:用来接收溢出的位置实参,溢出的位置实参会被*保存成元组的格式然后赋值给紧跟其后的形参名
# *后跟的可以是任意名字,但是约定俗成应该是args
def func(x,y,*z):
print(x,y,z)
func(1,2,3,4,5)#实参溢出的3,4,5会以元组的形式赋值给*z
# 其实args也只是一个变量名而已,真正起作用的是*这个符号
# 输出结果:1 2 (3, 4, 5)
def my_sum(*x):# 规范命名为*args --》应该写成--》def my_sum(*args)(*args是一种命名规范,当其它程序看到它时就会明白这是个可变长参数)
res = 0
for item in x:
res += x
return res
res = my_sum(1, 2, 3, 4, 5, 6)
print(res)
# 输出结果: 21
三、来为大家讲下**kwargs吧
# 可变长度的关键子参数
# **形参名:用来接收溢出的关键子实参,溢出的关键字实参会被*保存成字典的格式然后赋值给紧跟其后的形参名
# **后跟的可以是任意名字,但是约定俗成应该是kargs
def func(x, y, **kargs):
print(x, y, kargs)
func(1, y=2, a=1, c=3) # a=1,c=3是溢出的关键字实参
# 运行结果为: 1 2 {'a': 1, 'c': 3}
四、让我们更加深刻的来探讨它们的密码吧
# *可以用在实参中,实参中带*,先*后的值打散成位置实参
def func(x,y,z):
print(x,y,z)
func(*[11,22,33])#==> func(11,22,33) []里面的元素个数必须与位置形参个数一样
# 输出结果: 11 22 33
# 形参与实参中都带*
def func(x, y, *args):
print(x, y, args)
func(1, 2, *[3, 4, 5, 6]) # 打散成func(1,2,3,4,5,6)==>输出 1,2(3,4,5,6)
func(1, 2, [3, 4, 5, 6]) # ==》输出 1,2,([3,4,5,6])
func(*'hello') # 打散成func('h','e','l','l','o')==》输出 h e('l','l','o')
# 输出结果:
'''
1 2 (3, 4, 5, 6)
1 2 ([3, 4, 5, 6],)
h e ('l', 'l', 'o')
'''
# **可以用在实参中(**后跟的只能是字典),实参中带**,先**后的值打散成关键字实参
def func(x,y,z):
print(x,y,z)
func(*{'x':1,'y':2,'z':5})#打散成 func('x','y','z')
# 输出结果:x y z
func(**{'x':1,'y':2,'z':5})#打散成 func(x=1,y=2,z=5)
# 输出结果:1 2 5
def func(x, y, **kwargs):
print(x, y, kwargs)
func(**{'x': 1111, 'y': 2222, 'a': 3333, 'b': 4444}) # 打散成 func(x=1111,y=2222,a=3333,b=4444)
# 输出结果:1111 2222 {'a': 3333, 'b': 4444}
# 混用 *args必须放在**kwargs之前
# 在定义函数时,*后定义的参数,如下所示,称之为命名关键子参数
# 命名关键子实参必须按照key=value形式为其传参
def func(x, y, *, a, b): # 其中,a和b称之为命名关键子参数
print(x, y)
print(a, b)
func(1,2,a=22,b=44)
#输出结果: 1 2
def func(x, y, *, a=2222, b): # 命名关键字形参中默认赋值的参数不用必须在后面
print(x, y)
print(a, b)
func(1, 2, b=44)
# 输出结果:
'''
1 2
2222 44
'''
# 组合使用
# 位置形参,默认形参,*args,命名关键字形参,**kwargs 位置按照如下顺序
def foo(x, y, *args, a=1, b, **kwargs):
print(x, y)
print(args)
print(a)
print(b)
print(kwargs)
foo(1, 2, 3, 4, 5, b=3, c=4, d=5)
# 输出结果
'''
1 2
(3, 4, 5)
1
3
{'c': 4, 'd': 5}
'''
def func(x,y,z,a,b,c):
print(x)
print(y)
print(a)
print(b)
print(c)
# func(11,y=22,*[33,44],**{'b':55,'c':66})
# 打散 func(11,y=22,33,44,b=55,c=66)会报错,位置实参33此时在关键字实参y=22后面(位置形参应该在关键字形参后面)
func(11, 33, 44, a=22, **{'b': 55, 'c': 66})
# 输出结果
'''
11
33
22
55
66
'''
func(11,33,44,a=22,b=55,c=66)
# 输出结果
'''
11
33
22
55
66
'''