前言:
之前忘记做这个关于函数参数的博客了,现在补上,没办法,小小的强迫症。
实参和形参不得不说的故事
函数的参数分为形式参数和实际参数,简称形参,实参。
- 形参就是函数定义时括号里声明的参数,实际就是变量名,用来接收函数调用时传过来的值。
- 实参即在调用函数时,括号里传的值,值可以是常量,变量,表达式,或三者的组合。
在调用函数时,实参值赋值给形参。在python中,值和变量名是单纯的绑定关系,对于函数来说,这种绑定只在调用函数时生效,调用结束,绑定解除。
# 实参是常量
res = minimum(1,2)
# 实参是变量
a = 1
b = 2
res = minimum(a,b)
# 实参是表达式
res = minimum(10*9,9+minimum(2,3))
# 实参值是三者的组合
a = 2
b = 4
res = minimum(10*9+a,b,4)
形参实参的具体使用
1.位置参数
位置参数即顺序参数,定义形参时从左到右,那么实参必须传值,且按照从左到右的顺序一一传值。
def register(name,age,sex): #定义位置形参:name,age,sex,三者都必须被传值
print('Name:%s Age:%s Sex:%s' %(name,age,sex))
# register() #TypeError:缺少3个位置参数
register("周安可",18,"女") # 从左到右一一对应
2.关键字参数
实参以key = value这样的形式调用函数,被称为关键字参数,传参顺序可以随意。
# 对上面的函数这样传参
register(age=18,name="萧知南",sex="女")
需注意:关键字传参和位置参数可以混合使用,但两点要求:
- 关键字参数必须在位置参数后面。
- 不可对关键字参数重复赋值。
3.默认参数
默认参数就是在函数定义阶段就赋予初值的参数。对于一些不需要经常赋值的参数可以把它们作为默认参数。这样就会减少函数调用的复杂性。
# 对于女子学院来说,性别都是女,故可以将sex=‘女’、
def Girl_school(name,age,sex='女'):
print(name,age,sex)
# 传值时:
Girl_school("李清雨",18) # 可以不对sex传参
需注意:
- 默认参数只在定义时赋值一次。
- 必须放在位置参数后面。
- 通常定义成不可变类型。
x = 1
def foo(n=x): # 仅仅在定义时被赋值一次,故n的默认值是1
print(n)
x = 6 # x改变,n的默认值不变
foo()
# 通常定义成不可变类型
def add_list(n,alist=[]):
alist.append(n)
return alist
add_list(1)
# 返回:[1]
add_list(1)
# [1,1]
add_list(1)
# [1,1,1]
# 每次调用都是在上一次的基础上向列表添加值。
修改:
def add_list(n,alist=None):
if alist is None:
alist=[]
alist.append(n)
return alist
add_list(1)
# 返回:[1]
add_list(1)
# [1]
add_list(1)
# [1]
4.可变长参数(*和 ** 用法)
可变参数就是在函数调用时,实参的个数是不固定。而实参的定义无非两种:位置参数,关键字参数。故而提出两种解决方案。
4.1:可变长的位置参数
利用 *args 来定义形参。它会接收多出的位置参数,并以元组的形式返回。
ps: 你可以这样理解,注意有 * 时这就好比“解压”。即 *args 将元组(或者序列)解压缩。而args就是将多余的位置参数给压缩到元组中。
def F(a,b,c,*args):
print(*args)
print(a,b,c,args) # args得到的是一个元组
F(1,2,3,4,5,6) # 多余出的参数都被*接收,以元组形式赋值给args
F(1,2,3,*[4,5,6]) # 结果和上面的一样
# 结果:4 5 6
# 1 2 3 (4, 5, 6)
F(1,2,3,[4,5,6]) # 将[4,5,6]作为普通的位置参数处理
# 结果:[4,5,6]
# ([4,5,6],)
4.2:可变长的关键字参数
利用 **kwargs 来定义形参,用于接收多余出的关键字参数。
可以和 *args 一样理解。只不过变成了字典形式
def GOO(a,**kwargs):
print(a)
print(kwargs) # 将多余的关键字参数传给**,然后以字典的形式赋值给kwargs
GOO(a=1,b=2,c=4)
# 1
# {'b': 2, 'c': 4}
GOO(1,**{'b':2,'c':4}) # 结果和上面一样
2.5命名关键字参数
使用 * 作为分隔符,其之后的参数是命名关键字参数,在进行实参传值时,必须是关键字参数的形式,并且必须传值。
def HaHa(a,b,*,c,d):
pass
HaHa(1,2,3,4) # 出错!*后位命名关键字参数必须是关键字参数的形式
HaHa(1,2,c=3,d=4) # 正确
注意:当命名关键字参数前有*args时,就不再需要 *作为分隔符了。
并且命名参数也可以由默认值。如下方示例:
def HaHa(a,b,*args,c=8,d): # 需注意c,d是命名关键字参数,故c=8可以放在d之前。
pass
HaHa(1,2,3,d=4) # 传参正确
组合使用
综上所述,所有参数可以任意组合使用。但是,定义参数的顺序必须是:
位置参数,默认参数,* args,命名关键字参数,**kwargs
def foo(x,y,z=1,*args,a=1,b,**kwargs):
print(x,y,z)
print(args)
print(a,b)
print(kwargs)
foo(1,2,3,4,5,b=3,c=4,d=5)
"""
结果:1,2,1
(3,4,5)
1,3
{'c':4,'d':5}
"""