1、 函数的参数
位置参数指的是位置形参
在定义函数时,按照从左到右的顺序依次定义形参,称为位置形参,凡是按照这种形式定义的形参都必须被传值
def register(name,age):
print(name,age)
register(1,2)
不传递参数会报错类型错误
def register(name,age):
print(name,age)
register()
TypeError:缺少2个位置参数
TypeError: register() missing 2 required positional arguments: 'name' and 'age'
2、 关键字参数
关键字参数指的是关键字实参
在调用函数时,实参可以是key=value的形式,称为关键字参数,凡是按照这种形式定义的实参,可以完全不按照从左到右的顺序定义,但仍能为指定的形参赋值
def register(name, age):
print(name, age)
register(age=18, name='lisi')
需要注意在调用函数时,实参也可以是按位置或按关键字的混合使用,但必须保证关键字参数在位置参数后面,且不可以对一个形参重复赋值
def register(name, age):
print(name, age)
register(age=18, 'lisi') #SyntaxError
SyntaxError: positional argument follows keyword argument
def register(name, age):
print(name, age)
register(age=18, age ='lisi') #syntaxError 重复赋值语法错误
3、默认参数
默认参数指的是默认形参
在定义函数时,就已经为形参赋值,这类形参称之为默认参数,当函数有多个参数时,需要将值经常改变的参数定义成位置参数,而将值改变较少的参数定义成默认参数。例如编写一个注册学生信息的函数,如果大多数学生的性别都为男,那完全可以将形参sex定义成默认参数
def register(name, age, sex='male'):
print(name, age, sex)
register(name='lisi', age=18)# 大多数情况下不传值给默认参数
register(name='lisi', age=18, sex='man') # 可以传值给默认参数
默认参数必须在位置参数之后否则会报语法错误
def register(sex='male', name, age): #SyntaxError: non-default argument follows default argument
print(name, age, sex)
register(name='lisi', age=18)
默认参数的值只能在定义阶段被赋值一次,在函数体内赋值无效,在函数体外赋值也无效
age=18 #体外赋值
def register(age=17):
print(age)
age = 16 #体内赋值
register()
默认参数的值通常应设为不可变类型,函数定义之后可能会有很多次调用我们可能无法预知最后的结果,一般我们都会使用if进行一次判断将默认参数值定义为空值
每次调用是在上一次的基础上向同一列表增加值,修改如下
默认参数的值不要定义成可变类型,如果非要定义那就定义成空值
def func(x, y, z, l=None):
if l is None:
l = []
l.append(x)
l.append(y)
l.append(z)
print(l)
func(1, 2, 3)
Newland=[7, 8, 9]
func(4, 5, 6, Newland)
def func(x, y, z, l=None):
if l is None:
l = []
l.append(x)
l.append(y)
l.append(z)
print(l)
func(1, 2, 3)
func(4, 5, 6)
4、可变长度的参数 (与的用法)
调用函数一般指的是实参。
参数的长度可变指的是在调用函数时,实参的个数可以不固定,而在调用函数时,实参的定义无非是按位置或者按关键字两种形式,这就要求形参提供两种解决方案来分别处理两种形式的可变长度的参数
可变长度的位置参数
一个实参加上号,在调用函数时,多出的位置实参,都会被匹配*有表示正则的意思,被匹配的元组会以元组的形式赋值给形参
例子:
def fee(x, *args):
print(x)
print(args)
fee(1, 2, 3)
输出结果:
1
(2, 3)
例子
def fee(x, *args):
print(x)
print(args)
l=[7, 6, 4]
fee(1, 2, 3 ,*l) # *l就相当于位置参数7, 6, 4
输出结果:
1
(2, 3, 7, 6, 4)
实参为默认实参依然可以使用*的形式
def fee(x, y=2, *args):
print(x)
print(y)
print(args)
fee(*[1,2,3,4])
求多个值的和
def add(*args):
res=0
for i in args:
res+=i
return res
add(1,2,3,4,5)
15
5、可变长度的关键字参数
形参名前加号,那么在调用函数时,溢出的关键字参数,都会被接收,以字典的形式保存下来赋值给该形参
def fee(x, **kwargs):
print(x)
print(kwargs)
fee(x=1, z=2, y=3)
事先生成了一个字典,仍然是可以传值给**kwargs的
def fee(x, **kwargs):
print(x)
print(kwargs)
dis={'a':7, 'b':9}
fee(x=1, **dis)
参为常规参数(位置或默认),实参仍可以是**的形式
def fee(x,y,z=1):
print(x)
print(y)
print(z)
fee(**{'x':1, 'y':2})
编写一个用户认证的函数,起初可能只基于用户名密码的验证就可以了,可以使用**kwargs为日后的扩展供良好的环境,同时保持了函数的简洁性。
def fee(name, password, **kwargs):
pass
组合使用
可变参数args与关键字参数kwargs通常是组合在一起使用的,如果一个函数的形参为args与kwargs,那么代表该函数可以接收任何形式、任意长度的参数
def rep(*args,**kwargs):
pass
在该函数内部还可以把接收到的参数传给另外一个函数
def dls(x,y,z):
print(x,y,z)
def tls(*args,**kwargs):
dls(*args,**kwargs)
tls(1,z=3,y=2)
按照上述写法,在为函数wrapper传参时,其实遵循的是函数func的参数规则,调用函数wrapper的过程分析如下:
位置实参1被接收,以元组的形式保存下来,赋值给args,即args=(1,),关键字实参z=3,y=2被接收,以字典的形式保存下来,赋值给kwargs,即kwargs={‘y’: 2, ‘z’: 3}
执行func(args,kwargs),即func((1,), {‘y’: 2, ‘z’: 3}),等同于func(1,z=3,y=2)
提示: *args、**kwargs中的args和kwargs被替换成其他名字并无语法错误,但使用args、kwargs是约定俗成的。