一、形参与实参
1、形参:在定义函数阶段所定义的参数称为形式参数,即形参,相当于变量名。
2、实参:在调用函数阶段所传入的参数称为实际参数,即实参,相当于变量值。
def func(a, b): # 定义函数时的参数a,b即为形参 res = a + b return res num_sum = func(1, 2) # 调用函数时的参数1,2即为实参
3、形参与实参的关系:
①在调用阶段,实参的值会绑定给形参,类似于变量的赋值操作,变量值绑定给变量名。
②这种绑定关系只能在函数体内使用。
③调用函数时,实参与形参的绑定关系生效,函数体代码执行完,即函数调用完成后即解除绑定关系。
4、实参传入值的形式:
①直接传值:
def func(a,b): pass func(1,2) # 直接把值填入括号内作为实参传入
②通过变量名:
def func(a,b): pass a = 1 b = 2 func(a,b) # 在括号内填入变量名a,b就相当于把它们对应的值1,2填入
③把系统功能或自定义函数的返回值传入:
def func(a,b): res = a+b return res func(int('1'),func(2,3)) # 返回值作为实参
二、形参与实参的具体使用
1、位置参数:按照从左到右的顺序依次定义的参数称为位置参数。
①位置形参:在函数的定义阶段,从左到右依次定义的参数名,必须被传值,传入值的数量要与参数名数量完全一致。
def func(a,b): pass func(1) func(1,2,3) # 作为传入值的实参数量与形参数量相比,过多过少都会报错
②位置实参:在函数的调用阶段,从左到右依次传入的参数值,按照位置与形参一一对应。
def func(a,b): pass func(1,2) #值 1 对应形参 a ,值 2 对应形参 b
2、关键字参数:在函数的调用阶段,按照key=value的形式传入值,key对应形参名,value对应传入值,顺序无影响,但数量需要对应一致。
def func(a, b): pass func(b=2, a=1) # 以关键字形式传参数值,不用必须按照从左到右依次的顺序 func(b=2, c=3) # 不能为不存在的参数传值,报错
3、位置参数与关键字参数混用的原则:
①位置参数必须放在关键字参数前面。
def func(a, b): pass func(b=2,1) # 报错
②不能为同一个参数重复传值。
def func(a, b): pass func(1,a=2) # 报错
4、默认参数:
①定义:在函数的定义阶段,就已经被赋值的形参,称为默认参数,这种函数的调用阶段,因为该参数已被赋值,可以不用再为其赋值,若赋值则覆盖默认值。
def func(a, b=2): pass func(1) # 只对形参名 a 赋值为 1,b 仍为默认值 2 func(1,3) # 实参对 b 传入值 3 ,则 b 的值会被覆盖为 3
②位置参数与默认参数混用的原则:位置参数必须放在默认参数前面。
def func(a=1,2): # 报错 pass
③默认参数的约定规范:赋值类型应该为不可变类型,否则有可能出现函数体不封闭的情况。
x = [22,33] def func(a,b=x): print(a,b) func(1) # 结果为 1 [22, 33] x[0] = 44 func(1) # 结果为 1 [44, 33],默认参数值因列表的特性而导致因外界变化而同步变化了
5、可变长度参数:*与**的用法。
①定义:可变长度是指在调用函数时,传入值的数量可能不固定,因为形参与实参需要遵循数量一致的原则,那么数量溢出的实参需要有对应的形参来接收。
②可变长度位置参数:
Ⅰ:可变长度位置形参:形式为,*形参名,溢出的位置参数会组成为一个元组赋值给该形参名,此种形参名原则上可以是任意合法形参名,但约定上用*args。
def func(a,*args): pass func(1,2,3,4,5,6) # 相当于 args = tuple(2,3,4,5,6)
Ⅱ:可变长度位置实参:形式为,*可遍历类型,会先解压出各个元素,再依次赋值给对应形参名。
def func(a,b,c,d,e,f): pass func(1,*[2,3,4,5,6]) # 相当于把 2,3,4,5,6 依次赋值给 b,c,d,e,f
Ⅲ:形参与实参都为可变长度位置参数:先把可变长度位置实参解压,再由可变长度位置形参接收。
def func(a,*args): pass func(1,*[2,3,4,5,6]) # 先把 2,3,4,5,6解压出来,再由 args 接收组成 tuple(2,3,4,5,6)
③可变长度关键字参数:
Ⅰ:可变长度关键字形参:形式为,**形参名,溢出的关键字参数会组成为一个字典赋值给该形参名,此种形参名原则上可以是任意合法形参名,但约定上用**kwargs。
def func(a,**kwargs): pass func(a=1,b=2,c=2) # 相当于 kwargs = dict{'b':2,'c':3}
Ⅱ:可变长度关键字实参:形式为,**dict,会先把字典中的键值对解压成key=value的形式,再赋值给对应形参名。
def func(a,b,c): pass func(a=1,**{'b':2,'c':3}) # 相当于以 b=2,c=3的形式赋值给对应形参名
Ⅲ:形参与实参都为可变长度关键字参数:先把可变长度关键字实参解压,再由可变长度关键字形参接收。
def func(a,**kwargs): pass func(a=1,**{'b':2,'c':3}) # 把 {'b':2,'c':3} 解压为 b=2,c=3,再由 kwargs 接收组成 dict{'b':2,'c':3}
④可变长度位置参数与可变长度关键字参数混用:即*args与**kwargs。
Ⅰ:原则:根据位置参数必须放在关键字参数前面的原则,*args也必须放在**kwargs的前面。
def func(a,*args,**kwargs): pass func(1,2,3,4,e=5,f=6) # 即,a=1,args=tuple(2,3,4),kwargs={'e':5,'f':6}
Ⅱ:万能嵌套:
def func1(a, b, c, d, e): pass def func2(*args, **kwargs): func1(*args, **kwargs) func2(1, 2, 3, d=4, e=5) # 此时无论func2传入多少任意类型实参,都会被func2的形参分类压缩收集, # 然后func2的形参被赋值后再作为func1的实参解压传给func1的对应形参, # 这样当调整func1的参数数量时完全不需要调整func2