Python 函数的参数详解 一、 形参与实参

形参:即在定义函数时,括号内声明的参数。形参本质就是一个变量名,用来接收外部传来的值。
实参:即在调用函数时,括号内传入的值,值可以是常量、变量、表达式或三者的组合。

def func(x,y)  #x,y是形参
	pass
func(10,11)  #10,11是实参

注意:在调用函数时,实参值(变量的值)会赋值给形参(变量名),两者的绑定关系只在函数调用时才会生效,在调用函数结束后就立刻接触绑定

1.1、参数的形式

1、位置参数:通过位置从左到右的顺序依次定义的参数

def foo(a,b)
	print(a,b)
foo(1,2)

注意:
1、位置形参的特性是在调用函数时必须为其传值,而且多一个少一个都不行
2、位置实参与形参一一对应

2、关键字参数:在调用函数时,按照key=value的形式定义的实参,称为关键字参数

def foo(x,y,z):
	print(x,y,z)1
foo(x=1,y=2,z=3)
注意:
1、相当于指名道姓地为形参传值,意味着即便是不按照顺序定义,仍然能为指定参数传值
2、在调用函数时,位置实参与关键字实参可以混合使用,但关键字实参必须要放在位置实参后,不能为同一个形参重复传值

3、默认参数:在定义阶段,已经为某个形参赋值,那么该参数称为默认参数

注意:
1、定义阶段已经有值,意味着调用阶段可以不传值,但如果在实参的时候传入新参数,就会使用新参数
def register(name,age,sex='male'):
	print(name,age,sex)
register('egon',18,'male')
register('alex',73,'female')
register('wxx',84,'male')

2、默认参数的值只在定义阶段赋值一次,也就是说默认参数的值在定义阶段就固定死了
m = 10
def foo(x,y=m)
	print(x,y)
m=111111
foo(1)
>>>1,10
>

3、默认参数在传值的时候,不要将可变类型当作参数传值
def register(name,hobby,l=[]):
    l.append(hobby)
    print(name,l)
register('egon','play')
register('alex','AK')
register('wxx','gun')


def register(name,hobby,l=[]):
    l.append(hobby)
    print(name,l)
register('egon','play',[])	#egon ['play']
register('alex','AK',[])	#alex ['AK']
register('wxx','gun',[])	#wxx ['gun']


def register(name,hobby,l=None):
    if l == None:
        l=[]
        l.append(hobby)
        print(name,l)
register('egon','play')  #egon ['play']
register('alex','AK')	#alex ['AK']
register('wxx','gun')	#wxx ['gun']



应用:对于经常需要变化的值,需要将对应的形参定义为位置形参,对于大多数值都一样的情况,需要将对于的形参定义成默认形参。

4、可变长参数:可变长指的是参数的个数可以不固定。实参有按位置定义的实参 和 按关键字定义的实参,所以可变长的实参指的就是按照这两种形式定义的实参个数可以不固定,然而实参终究是要给形参传值的,所以形参必须要有两种对应的解决方案来分别处理以上两种形式可变长度的实参

foo(1,2)
foo(1,2,3)
foo(1,2,3,4)

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

形参包含*/**

*会将溢出的位置实参全部接受,然后保存成元组的形式赋值给args


def foo(x,y,z,*args):
	print(x,y,z)
	print(args)
foo(1,2,3,4,5,6)
>>>123
>>>(4,5,6)
**会将溢出的关键字实参全部接受,然后保存成字典的形式赋值**后面的变量中
def foo(x,y,z,**kwargs):
	print(x,y,z)
	print(kwargs)
foo(x=1,y=2,z=3,d=4,f=5,e=6)
>>>1 2 3
>>>{'d': 4, 'f': 5, 'e': 6}

实参里包含*/**

*:一旦碰到实参加*,打散你传入的容器类型

def foo(x,y,z,*args):
	print(x,y,z)
	print(args)
foo(1,2,3,*[4,5,6])     #--->foo(1,2,3,4,5,6)
>>>1 2 3
>>>(4, 5, 6)
**:一旦碰到实参加**,就把字典打散成关键字参数传入形参

#定义函数
def test(*args, **kwargs):
    print(args)
    print(kwargs)
#定义一个元组和一个字典
tuple = (1,2,3,4,5)
dict = {'a':1,'b':2,'c':3}
#tuple和dict两个参数会作为一个元组传递给*args参数,而没有实参传递给**kwargs参数。
test(tuple,dict)
>>>((1, 2, 3, 4, 5), {'a': 1, 'b': 2, 'c': 3})
>>>{}
#打散传参
test(*tuple, **dict)  #test(1,2,3,4,5,a=1,b=2,c=3)
>>>(1, 2, 3, 4, 5)
>>>{'a': 1, 'b': 2, 'c': 3}

组合使用:如果一个函数的形参为*args与**kwargs,那么代表该函数可以接收任何形式、任意长度的参数

def wrapper(*args,**kwargs):
	print(args)
	print(kwargs)
wrapper(1,2,3,4,5,6,x=6666,y=2222)
>>>(1, 2, 3, 4, 5, 6)
>>>{'x': 6666, 'y': 2222}

5、命名关键字参数(了解)
格式:在后面的参数都是命名关键字参数
特征:
后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递

def index(x, y, z, a=1, *args, b, **kwargs):
    print(x, y, z)
    print(a)
    print(args)
    print(b)
    print(kwargs)

index(1, 2, 3,354353, 4342, 3213123, b=222, c=333, d=444)
输出结果:
1 2 3
354353
(4342, 3213123)
222
{'c': 333, 'd': 444}