Python之形参实参详解

python函数中重要的一部分就是参数的调用,今天对参数进行讲解。
参数大体上分为两种:
形参(形式参数):在定义函数阶段定义的参数称之为参数,粗略的可以认为是变量名。
实参:在调用函数阶段传入的值称之为实际参数,简称实参,粗略的可以认为是变量值。
首先清楚一下几点:
1.在调用函数阶段,实参会绑定给形参,且这种关系只能在函数体内用,结束后即被收回。
2.实参被赋予的相当于变量名的地址(后面会有解释)。
按照作用分又有以下几种:
1.位置参数:
1.1位置形参:按照从左往右的顺序依次定义的变量名,且必须被传值,多一个少一个都不行

def func(x,y):
    print(x*y)
func(2,3)

1.2位置实参:按照从左往右的顺序依次定义的变量名,一一对应

def func(x,y):
    print(x*y)
func(1,2)#2
func(2,1)#2

2.关键字实参:在函数调用的阶段,按照键值对的方式传入值可以完全不参照顺序,给某个形参传值。

def func(x,y):
    print(x*y)
func(x=2,y=3)#6
func(y=3,x=2)#6

需要注意的是:位置形参可以和关键字实参混合使用,但必须在关键字实参之前:
错误示范:

def func(x,y):
    print(x*y)
func(x=2,3)#SyntaxError: positional argument follows keyword argument

同时还应该避免向用同一个形参传值。
3.默认形参:在函数定义阶段,就已经被赋值的形参。

def func(x,y = 3):
    print(x*y)
func(x = 1,y=2)#2

此时如果给默认参数赋予一个新的值,那么就会覆盖默认值。
同样位置形参可以和默认形参混用,但需要注意的是:
(1):位置形参必须在默认形参的左边(可以认为位置形参具有较高的优先级)
错误示范:

def func(x =2,y):
    pass#SyntaxError: non-default argument follows default argument

需要注意到一点:默认参数的值是在函数定义阶段被赋予的,被赋予的是值的内存地址。

m=[1111,]
def func (x,y=m):
    print(x,y)#1 [1111, 111]
    print(type(y))#<class 'list'>
m.append(111)
func(1)

4.可变长度参数(*与**的使用)
可变长度是指在调用函数时,传入的值(实参)不固定:
实参是给形参赋值的,所以多余的实参必须要有对应的形参接收:
4.1位置参数:(*args) 输出类型为元组。
举例:

def func(x,y,*z):
    print(x,y,z)
func(1,2,3,4,5)

这时候对应关系为x:1,y:2,z:(3,4,5)。
结果为:

1 2 (3, 4, 5)
<class 'tuple'>

同时也可以打印列表。

def func(x,y,*z):
    print(x,y,z)
    print(type(z))
func(1,2,[3,4,5])
1 2 ([3, 4, 5],)
<class 'tuple'>

实例:多个数相加:

def func(*x):   #多个数相加
    res = 0
    for item in x:
        res+=item
    print(res)

func(1,2,3)#6

关键字参数:(**kwargs) 输出为字典。
举例:

def func(x,y,**kwargs):
    print(x,y,kwargs)
    print(type(kwargs))#字典

func(1,2,z = 3,c = 4)
1 2 {'z': 3, 'c': 4}
<class 'dict'>

补充:* 可以用在实参中,实参中带 * ,把*后面的值拆分成实参。
ex:

def func(x,y,*z):
    print(x,y,z)

func(*[1,2,3,4])#1 2 (3, 4)

调用过程中把列表拆开分为1,2,3,4 再与定义阶段对应:x:1,y:2,z:(3,4)
同样的: ** 用在实参中,
** 后跟的是字典,把* * 后面的值打散成关键字实参

def func(x,y,z):
    print(x,y,z)
func(**{'x':1,'y':2,'z':3})#1 2 3  把字典拆分后输出变量值
func(*{'x':1,'y':2,'z':3})#x y z  可以理解为*拆分后引用变量名

若形参和实参中都带**:

def func(x,y,**kwargs):
    print(x,y,kwargs)
func(**{'x':1,'y':2,'z':3,'v':4})
1 2 {'z': 3, 'v': 4}

调用阶段字典先被拆分,使x对应1,y对应2,后面的关键字参数又被输出为字典重新打印成{‘z’: 3, ‘v’: 4}

混用* 与**:*args必须在**kwargs之前:
ex:

def func(*args,**kwargs):#考虑扩展性
    print(args)
    print(kwargs)

func(1,2,3,x = 1,y = 2,z = 3)

*args的作用应该是使前三个元素输出为元组,后面关键字参数输出为字典

(1, 2, 3)
{'x': 1, 'y': 2, 'z': 3}

循环调用:

def index(x,y,z):
    print("=>>>>>",x,y,z)

def wrapper(a,b,c):
    index(a,b,c)
    print(index)  #循环调用

wrapper(1,2,3)

解释:wrapper调用了1,2,3,并传给wrapper函数体内的index(a,b,c),此时打印index应该是其内存的地址,又触发index函数体

=>>>>> 1 2 3
<function index at 0x02CC7FA0>

5.命名关键字参数(了解)
在定义函数时,*后定义的参数,如下所示称之为命名关键字参数
特点:
1.必须按照key =value的形式为其传值

def func(x,y,*,a,b):#a和b称之为命名关键字参数
    print(x,y)#1 2
    print(a,b)#111 222
func(1,2,b = 222,a = 111)
def func(x,y,*,a=111,b ):#a和b称之为命名关键字参数  a是给命名关键字参数赋了值
    print(x,y)#1 2
    print(a,b)111 222
func(1,2,b =222)

6.组合使用:(了解)
形参顺序:位置形参,默认形参,*args ,命名关键字参数, **kwargs

def func(x,y = 111,*args,z,**kwargs):
    print(x)
    print(y)
    print(args)
    print(z)
    print(kwargs)

实参顺序:

def func(x,y,z,a,b):
    print(x)
    print(y)
    print(z)
    print(a)
    print(b)
func(1,*[1,2],**{'a':11,"b":222})

由于5和6没有实际需求场景,所以用处不太大,仅为了解。