14---函数的参数

一。形参和实参

# 形参(形式参数)和实参(实际参数)
# 形参:再定义函数阶段定义的参数称之为形式参数,简称形参,相当于变量名
def fun(x,y):
    print(x,y)
# 实参:在调用函数阶段传入的值称为实际参数,简称实参,相当于变量值
fun(1,2)

# 形参与实参的关系:
# 在调用阶段,实参(变量值的内存地址)的值绑定给形参(变量名)
# 这种绑定关系只能在函数体内使用
# 实参与形参的绑定关系在函数调用时生效,在函数调用结束后,解除绑定关系

# 实参相当于值,值可以是以下形式
# 形式一
fun(1,2)
# 形式二
a = 1
b = 1
fun(a,b)
# 形式三
fun(int('1'),2)
fun(fun(2,3),2)

二。形参具体使用

# 形参:定义函数阶段时的参数(变量名)
# 位置形参:必须被传值(变量值),多一个不行少一个也不行
def add(x,y):
    print(x,y)
add(1,2)


# 默认形参:在定义函数时被赋值的形参,准确的说是被赋予值的内存地址   # 默认参数不传值的情况下,使用定义函数时的值   def add(x,y=2):   print(x,y)   add(1)   # 默认参数传值的情况下,使用调用函数时传的值   def add(x,y=2):    print(x,y)   add(1,4)
  
注意:虽然默认值可以被指定为任意数据类型,但是不推荐使用可变类型# 函数最理想的状态:函数的调用只跟函数本身有关系,不外界代码的影响

# 总结: 位置形参与默认形参混用: # 位置形参必须在默认形参的左边 # 默认参数最开始的值是在函数定义阶段被赋值的

三。实参具体使用

# 实参:函数调用阶段的参数(变量值)
# 位置实参:在函数调用阶段,按照从左到右的顺序依次给形参传值
#         特点:实参与形参一一对应,多一个不行少一个不行
def add(x,y):
    print(x,y)
add(1,2)
add(2,1)
# 关键字实参:在函数调用阶段,按照key=value的形式给形参传值
#           特点:指名道姓给某个形参传值,可以完全不参照顺序
def add(x,y):
    print(x, y)
add(x=1,y=2)
add(y=2,x=1)

# 总结:关键字实参一定要在位置实参之后
#       不能对同一个形参重复赋值

四。形参与实参的关系

1、在调用阶段,实参(变量值)会绑定给形参(变量名)
2、这种绑定关系只能在函数体内使用
3、实参与形参的绑定关系在函数调用时生效,函数调用结束后解除绑定关系

五。不定长位置参数和可变长度关键字参数

  1/不定长位置参数*args

# 可变长度位置形参*args:定义函数阶段:*形参,用来接收溢出的位置实参,溢出的位置实参会被*保存成元组的格式然后赋值紧跟其后的形参名
#               *后跟的可以是任意名字,但是约定俗成应该是args
def fun(x,y,*args):
    print(x,y,args)
fun(1,2,3,4,5,6)
:调用阶段:在实参中带*
# 实参中有*,先将*后的实参打散成位置实参,相当于调用for循环
def fun(x,y):
    print(x,y)
fun(*[1,2])
:定义阶段和调用阶段都有不定长位置参数*args
# 将实参*后的值打散成位置参数,按照位置传给形参,溢出的用定义函数时的不定长位置参数*args接收打包成元组
def fun(x,y,*args):
    print(x,y,args)
fun(*'hello')

  2\不定长关键字参数**kwargs

# 可变长度关键字参数**kwargs
#:定义函数阶段:**形参,用来接收溢出的关键字实参,溢出的关键字实参会被**保存成字典的格式然后赋值紧跟其后的形参名               
  **后跟的可以是任意名字,但是约定俗成应该是kargs
def fun(x,y,**kargs): print(x,y,kargs) fun(1,2,a=5,b=2) #:调用阶段:在实参中带** # 实参中有**,先将**后的实参打散成关键字 def fun(x, y): print(x, y) # fun(*{'k1':12,'k2':13}) 一个*是把字典的key传给形参 fun(**{'x':12,'y':13}) # 用两个星号给不定长关键字传值时,字典的key必须和函数的形参一致 # # :定义阶段和调用阶段都有不定长关键字参数**kwargs # # 将实参**后的值打散成关键字参数,传给形参,溢出的用定义函数时的不定长关键字参数**kwargs接收打包成字典 def fun(x, y, **kwargs): print(x, y, kwargs) fun(**{'a':1,'x':2,'y':5,'v':'789'})
强调:混用*与**:*args必须在**kwargs之前
# def func(x,*args,**kwargs):
#     print(args)
#     print(kwargs)
#
# func(1,2,3,4,5,6,7,8,x=1,y=2,z=3)

  3/不定长参数的应用

# 问题由来
def index(x, y):
    print('...', x, y, z)

def wrapper(a,b,c):
    index(a,b,c)

wrapper(1,2,3)
第一步:调用wrapper函数,将实参1 2 3分别赋值给形参a,b,c
第二步:此时a=1,b=2,c=3
第三步:在wrapper函数内部调用index函数,将a,b,c分别赋值给xyz
第四步:此时x=a=1,y=b=2,z=c=3
第五步:执行index函数内的代码
分析:1/因为在调用wrapper函数,会间接的调用index函数
     2/在调用index函数的时候,需要给三个形参传值
     3/index函数是通过wrapper函数间接调用的,所以需要通过wrapper间接为index的形参传实参
     4/所以wrapper函数的形参个数受到index函数的形参个数的限制
问题就是:如果修改了index的形参个数,那么相应的就要修改wrapper的形参个数,即牵一发而动全身,很麻烦


解决方式
将wrapper函数的形参定义为不定长位置形参和不定长关键字形参
所以在间接引用index函数的时候,就根据index形参的个数进行传参即可,当index函数形参个数发生变化时,wrapper函数无需进行改动
def index(x, y, z):
    print('...', x, y, z)


def wrapper(*args, **kwargs):
    index(*args, **kwargs)


wrapper(1, y=2, z=3)


# 第一步:调用函数wrapper
# 第二部:位置实参1传给不定长位置形参*args==>args = (1,)
#        关键字实参y=2,z=3传给不定长关键字参数==》kwargs={'y':2,'z':3}
# 第三步:间接调用index函数,发现实参是*args,**kwargs,先将args和kwargs打散成位置实参和关键字实参即 index(1,y=2,z=3)
# 第四步:将打散后的实参通过index函数的调用传给index函数的形参
# 这样不需要改动wrapper函数,就可以按照index函数的形参个数进行传值

猜你喜欢

转载自www.cnblogs.com/Kathrine/p/12518665.html