函数的参数
一、行参和实参介绍
函数的参数分为形式参数和实际参数,简称为形参和实参
形参:是在函数定义阶段中,即定义函数时括号里面的参数,本质是一个变量,是用来接收外部传来的值
实参:是在函数调用阶段中,即调用函数时括号里面的值,值是一个变量、常量、表达式或三则的组合
# 常量:my_min(1,2)
# 变量:a = 1
b =2
my_min(a,b)
# 表达式:a = 2
my_min(10*2,10*my_min(3,4)
)
# 三者组合:b = 2
my_min(1,b,10*my_min(3,4))
形参和实参的关系:
1.在调用阶段,实参(值)会绑定给形参(变量名)
2.这种绑定关系只能在函数体内使用
3.形参和实参的绑定关系是在函数调用时生效,当哈数调用结束后解除绑定关系
二、形参和实参的具体使用
1.位置参数:指在定义函数按照顺序定义的参数,为位置形参;在调用时按照形参的顺序传值,为位置实参
def fount(x,y): # 在定义函数时,从左到右依次定义的参数,称之为位置形参,必须被传值
print(x,y)
fount(1,2) # 调用函数时,按照从左到右依次定义的参数,称之为位置实参,必须与位置形参一一对应
注:定义函数时,形参定义了几个函数,在调用阶段也必须传几个值,调用函数中定义的参数必须喝定义函数时的参数保持一致,按照从左到右的顺序进行对应
2.关键字参数:在调用函数时,实参以key=value方式进行,称之为关键字参数,用这种方式定义的实参,可以不用按照顺序,但是任然要给指定的形参赋值
def fount(x,y):
print(x,y)
fount(y=2,x=1)
注:位置参数和关键字参数可以混合使用,但是关键字从参数必须放在位置参数后面,并且不能给同一个参数多次赋值
举例:def fount(x,y):
print(x,y)
fount(1,y=2) # 关键字参数必须放在位置参数后面,并且不能多次赋值
#fount(1,2,y=3) # 这种就会报错,位置参数为对应关系,这是1赋值给了x,2赋值给了y,后面进行了关键字参数又给y进行了赋值,多次给y赋值了
3.默认参数:在定义函数阶段时就已经给形参进行了赋值,这样称之为默认参数(也可以称之为默认形参),这里赋值是赋予的是内存地址
默认参数使用一:在定义函数阶段给形参赋值后,在调用阶段可以不用为其在赋值
def fount(x,y=2):
print(x,y) # 输出结果:1,2
fount(1) # 在定义函数时就已经给形参进行了赋值,这时在调用阶段时就不用在给形参赋值
注:默认参数主要用于:在函数有多个参数时,其中有的参数不经常该变,大部分时间都是这个值,特殊情况下才会改变这个值,这时使用默认参数
默认参数使用二:在定义函数阶段给形参赋值户,在调用阶段给形参进行赋值
def fount(x,y=2):
print(x,y) # 输出结果:1,3
fount(1,3) # 定义是已经给了给参数进行了赋值,但是在调用时又给其赋值了,这时形参就会以调用时的值为准,输出结果就会是1,3
默认参数使用三:默认参数的值通常应该设为不可变类型,如果是可变类型在调用函数时就不能预知到函数的结果了,函数体主要实现该函数的功能即可
函数最理想的状态:函数调用只跟函数本身有关系,不受外界代码的影响
def fount(x.y=[]): # 这里默认参数设为了可变类型,在函数体中进行实现代码就不能预知到该函数的结果
y.append(x)
print(x,y) # 这里就不能预知到输出的y的值了,这里就会输出1 [1],2 [1,2
fount(1)
funnt(2)
可以修上面代码为:
def fount(x,y=None):
if y is None:
y=[]
y.append(x)
print(x,y) # 这里就可以预知到y的值了,输出:1 [1],2 [2]
fount(1)
fount(2)
注:位置形参和默认形参可以混合使用,但是默认形参必须放在位置形参的后面,默认形参仅能在函数定义阶段被赋值一次
举例:y = 2
def fount(x,arg =y): # 默认形参必须放在位置形参后面,并且默认参数已经赋值了
print(x,arg) # 打印结果为:1,2
y = 3 # 在定义阶段已经被赋值了,这里的y和函数中的y没有任何关系
fount(1) # 为x赋值
三、位置参数、默认参数运用场景
位置参数:当值经常变化的情况下,这时定义为位置参数
默认参数:当值不经常变化,只是在少数情况是才会变化,这时可以使用默认参数,在调用时大多数情况就可以不用传值了,少数情况下进行传值
四、可变长度的参数(*与**的使用)
位置参数的长度可变:指的是在调用函数时,实参的个数可以不固定(实参的定义就两种,位置参数和关键字参数)
形参和实参是一一对应的关系,当实参的值不固定时,这时就需要形参提供方法来接收实参多余的值
1.可变长度的位置参数
实现形参接收实参多余的值:在定义参数时,在形参名前面添加*号,用来接收实参中多余的值,已元组的形式保存下来赋值给形参
使用方式一:形参中使用*号,接收溢出的位置实参,以元组的形式保存下来赋值给形参
def fount(x,y,*args): # 通常用*号来接收溢出的位置实参,形参名约定用args来表示(用其他的名字也没有错误)
print(x,y,args) # 打印结果为:1 2(3,4,5,6,7)
# 这里调用是使用的是位置实参,1、2按照位置给想,y赋值,多余的位置实参4、5、6、7都被*接收,以元组的形式保存下来,赋值给args,即args=(4, 5, 6,7)
fount(1,2,3,4,5,6,7)
使用方式二:实参中使用*号,传值给形参
def fount(x,y,*args):
print(x,y,args) # 输出结果为:1 2 (3,4,5,6) ;当调用函数是不加*,则输出:1 2 ([3,4,5,6]),就是普通的位置参数
L=[3,4,5,6]
fount(1,2,*L) # L相当于3 4 5 6,fount(1,2,*L)相当于fount(1,2,3,4,5,6),如果不添加*号,相当于把L当做值赋值给args,就是普通的位置参数
使用方式三:形参为常规的参数(位置或默认),实参仍以*的形式实现
def fount(x,y,z=3)
print(x,y) # 输出结果为:1 2 3
L=[1,2]
fount(*res) # 等同于fount(1,2)
使用方式四:*号的使用,当计算多个值的和
def add(*args):
res = 0
for i in add:
res += i
add(1.2.3.4.5)
2.可变长度的关键字参数
关键字参数的长度可变:指在调用函数时,按照关键字进行传值调用,实参key = value不固定(关键字参数定义为key=value方式)
形参中必须要有对应的值,当实参不固定时,这时就需要形参提供方法来接收溢出的关键字实参
使用方式一:形参中使用**来接收多余的关键字实参,以字典的形式保存下来赋值形参名
def fount(x,y,**kwargs): # 用**号来接收溢出的关键字实参,形参名约定用kwargs(用其他的名字也没有错误)
print(x,y,kwargs) # 输出结果为:1 2 {'a': 3, 'b': 4}
fount(y=2,x=1,a=3,b=4)
以上代码也可以用以下方式:
def fount(x,y,**kwargs):
print(x,y,kwargs)
dic ={'x':1,'y':2,'a':3,'b':4}
fount(**dic) # 如果在调用函数时,传入的值没有加**号,这表示一个普通的位置参数了
使用方式二:形参为常规参数(位置参数或默认参数),实参仍然可以用**的方式进行传值
def fount(x,y,z=3)
print(x,y,z)
dic = {'y':2,'x':1}
fount(**dic) # 相当于fount(y=2,x=1)
如果我们要编写一个用户认证的函数,起初可能只基于用户名密码的验证就可以了,可以使用**kwargs为日后的扩展供良好的环境,同时保持了函数的简洁性。
def fount(name,pwd,**kwargs):
pass
fount(值)
3.组合使用:参数可以任何组合,但是必须要有顺序
组合使用顺序:位置参数--默认参数--*args--命名关键字参数--**kwargs
通常可变参数*args和**kwargs组合在一起使用,那么代表函数可以接受任意形式、任意长度的参数
def fount(*args,**kwargs):
pass
在该函数内部还可以把接收到的参数传给另外一个函数
>>> def func(x,y,z):
... print(x,y,z)
...
>>> def wrapper(*args,**kwargs):
... func(*args,**kwargs)
...
>>> wrapper(1,z=3,y=2)
1 2 3
按照上述写法,在为函数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)
五、命名关键字参数
1.命名关键字参数方式:在定义函数阶段,*后定义的参数称之为关键字形参
举例:def func(x,y,*,a,b): # * 后的参数为关键字形参,在调用阶段传值时,必须以关键字实参进行传值
print(x,y,a,b)
func(1,2,b=4,a=3) # 在定义阶段时,a和b在* 之后,表示a和b为关键字形参,这里调用传值的时候也必须以关键字实参的格式进行传值
2.命名关键字参数的特点
在定义函数时,如果定义为关键字参数,那么在调用参数时,必须以关键字参数的方式传值,即key=value的方式传值