1.形参与实参
基本概念:
形参,形式参数,指的是定义函数时,括号内定义的参数,是某种意义上的变量名
实参,实际参数,指的是调用函数时,括号内传入的值,是某种意义上的变量值
注意点:
实参和形参的绑定关系只有在函数调用时才会生效,调用结束后解除绑定,释放空间。调用函数,就是把实参赋值给形参的过程
2.位置参数
位置即顺序,指的是从左到右的顺序依次定义的参数
2.1.位置形参
定义函数时,按照位置顺序定义的形参
def foo(x,y,z):
print(x,y,z)
foo(1,2) #程序报错
foo(1,2,3,4)#程序报错
foo(1,2,3)#程序运行正常
从上面的程序运行结果,可以总结到位置形参的特性:
#调用时必须为其传值,而且传入的值必须一个不多,一个不少
2.2.位置实参
调用函数时,按照位置顺序定义传入的值
位置实参特性:
位置实参必须与形参一一对应
3.关键字参数
在调用函数时,以key=value形式定义的实参,称为关键字实参,相当于指名道姓的为形参传值,即便是不按照顺序定义,仍然能为指定形参传值
def foo(x,y,z): print(x,y,z) foo(x=1,y=2,z=3) foo(x=1,z=2,y=3) foo(z=3,x=2,y=1)
#在以关键字参数为位置形参传值时,只要按照key=value的形式,就可以不用按照顺序
4.混合参数
在调用函数时,传入的实参同时有位置实参和关键字实参
def foo(x,y,z): print(x,y,z) # 位置实参必须翻到关键字实参的前面 foo(1,2,z=3) #正确 foo(x=1,2,3) #错误 # 必须遵循形参的规则 foo(1,2,y=3)#正确 foo(1,2,z=3)#错误 # 不能为同一个形参重复传值 foo(x=1,y=2,z=3)#正确 foo(1,x=2,y=3,z=4)#错误
5.默认参数
在定义阶段已经为某个形参赋值,那么该形参就被称为默认参数。可以传值也可以不传值,经常需要变的参数定义成位置形参,变化较小的参数定义成默认参数
def resgister(name,age,sex = "male"): print(name,age,sex) #1:默认参数已有值,,可以传值也可以不用传值 resgister("egon",18) resgister("alex",73,"female") resgister("wxx",45) #2:位置形参必须在默认参数的前面 def resgister(sex = "male",name,age): print(name,age,sex) resgister("alex",73,"female")#程序报错
def resgister(name,age,sex = "male",):
print(name,age,sex)
resgister("alex",73,"female")#程序正常
#3:默认参数的值,只在定义阶段赋值一次,也就是说在定义阶段默认参数已经写死了 m =10 def foo(x,y=m): print(x,y) m =100 foo(1)# 1 10 #4:默认参数的值应该设置成不可变类型 #默认参数的值是可变类型 def resgister(name,hobby,l = []): l.append(hobby) print(name,hobby,l)
#错误实例 resgister("egon","play")#egon play [‘play‘] resgister("alex","read")#alex read [‘play‘, ‘read‘] resgister("wxx","sleep")#wxx sleep [‘play‘, ‘read‘, ‘sleep‘]
#正确实例 resgister("egon","play",[]) #egon play [‘play‘] resgister("alex","read",[]) #alex read [‘read‘] resgister("wxx","sleep",[]) #wxx sleep [‘sleep‘] #把默认参数的值设置成不可变类型 def resgister(name,hobby,l = None): if l is None: l = [] l.append(hobby) print(name,hobby,l) resgister("egon","play") #egon play [‘play‘] resgister("alex","read") #alex read [‘read‘] resgister("wxx","sleep") #wxx sleep [‘sleep‘]
#对于经常需要变化的值,需要将对应的形参定义错位置形参,
#对于大多数情况值都一样的情况,需要将对应的形参定义成默认形参
6.可变长参数
可变长指的是实参的个数不确定
而实参有按位置的位置实参和按关键字的关键字实参两种形式,针对这两种形式的可变长,形参对于有两种解决方案来完整的存放他们分别是*args和**kwargs
*args:可变长度的位置形参。
*会将溢出的位置实参全部接收,然后保存成元组形式,赋值给args
*kwargs:可变长度的关键字形参。
**会将溢出的关键字参数全部接收,然后保存成字典形式,赋值给kwargs
*args和*kwargs主要的功能都是有*和**完成,后面的argshe kwargs都只是变量名,是什么并不重要,但是约定俗成,也就如此了。
*args是可变长的位置形参,所以也具有位置形参的一切特性,*后定义的参数必须被传值(默认参数除外),切必须以关键字形式传值
def foo(x, y, *args, a=1, b, **kwargs): print(x, y) print(args) print(a) print(b) print(kwargs)
#结果
1
2
(3, 4, 5)
1
3
{‘c‘: 4, ‘d‘: 5}
7.在实参中的*和**
在上面的学习中,形参中的*和**把溢出的位置实参和关键字实参分别存成了元组和字典,那么在实参中*和**又是有什么功能呢?
实参加*,就把该实参的值打散成字符串 def foo(x,y,z): print(x,y,z) foo(*[1,2,3])
#foo(*[123]) == foo(1,2,3) 实参加**,就把该实参的值打散成关键字参数 def foo(x,y,z,**kwargs): print(x,y,z) print(kwargs) foo(1,2,3,**{"a":4,"b":5})
#foo(1,2,3,**{"a":4,"b":5}) == foo(1,2,3,a=4,b=5)
#打散的关键字实参和位置实参重复
def foo(x,y,z,**kwargs):
print(x,y,z)
print(kwargs)
foo(1,2,3,**{"x":4,"b":5})
#TypeError: foo() got multiple values for argument ‘x‘