1、形参 与 实参是什么?
形参(形式参数):指的是在定义函数时,括号内定义的参数,形参其实就变量名
实参(实际参数),指的是在调用函数时,括号内传入的值,实参其实就变量的值
1 #x,y是形参 2 def func(x,y): #x=10,y=11 3 print(x) 4 print(y)
1 #10,11是实参 2 func(10,11)
注意:
实参值(变量的值)与形参(变量名)的绑定关系只在函数调用时才会生效/绑定, 在函数调用结束后就立刻解除绑定
2、位置参数 位置形参 位置实参
位置即顺序,位置参参数指的就是按照从左到右的顺序依次定义的参数
1 #在定义函数时,按照位置定义的形参,称为位置形参 2 def foo(x,y,z): 3 print(x,y,z) 4 5 #位置形参的特性是:在调用函数时必须为其传值,而且多一个不行,少一个也不行 6 foo(1,2) #少了一个数 报错 7 foo(1,2,3,4) #多了一个数 报错 8 9 #在调用函数时,按照位置定义的实参,称为位置实参 10 注意:位置实参会与形参一一对应 11 foo(1,3,2) #必须一一对应
在调用函数时,按照key=value的形式定义的实参,称为关键字参数
1 def foo(x,y,z): 2 print(x,y,z) 3 4 #相当于指名道姓地为形参传值,意味着即便是不按照顺序定义,仍然能为指定的参数传值 5 foo(2,1,3) #位置实参,一一对应 6 foo(y=2,x=1,z=3) #关键字实参 指名道姓 不需要顺序 7 foo(z=2,aaaa=1) #少了值 没有aaa 报错 8 9 #在调用函数时,位置实参与关键字实参可以混合使用,但必须 10 #必须遵循形参的规则 11 foo(1,z=3,y=2) #1,2,3 x=1,y=2,z=3 12 foo(1,z=3) #少了 报错 13 14 #不能为同一个形参重复传值 15 foo(1,x=1,y=3,z=2) #x重复传值 报错 16 17 #位置实参必须放到关键字实参的前面 18 foo(y=3,z=2,1) #位置实参应该 在 关键字实参前面 报错
4、默认参数
在定义阶段,已经为某个形参赋值,那么该形参叫默认参数
(1) 定义阶段已有值,代表着调用阶段可以不传值
1 def register(name,age,sex='male'): 2 print(name,age,sex) 3 4 register('sss',14) 5 register('ddd',18) 6 register('lll',74,'female') #传的话 用新值 7 register('nnn',54) 8 #sss 14 male 9 #ddd 18 male 10 #111 74 female 11 #nnn 54 male
1 def func(y=i,x): #报错,位置应该在默认形参的前面 2 pass
1 m=10 2 def foo(x,y=m) #这里 y已经是 m=10 了,不会再改变了 3 print(x,y) 4 5 m='jhhhhjhj' #再次定义也不会改变 y 的值 6 foo(1) #1,10 7 foo(1,11) #这里 y=11
1 def register(name,hobby,l=None): 2 if l is None: 3 l=[] 4 l.append(hobby) #l=['play'] 5 print(name,l) # wxx ['play'] 6 7 register('wxx','play') # wxx ['play'] 8 register('alex','read') # alex ['read'] 9 register('egon','music') # alex ['music'] 10 11 def register(name,hobby,l=[]): #如果是这种情况 l=[] 12 l.append(hobby) #为一个集合,可变类型 13 print(name,l)
应用:
对于经常需要变化的值,需要将对应的形参定义成 位置形参
对于大多数情况值都一样的情况,需要将对应的形参定义成 默认形参
5、可变长度参数
参数的个数不固定,实参有 按位置定义(*)的实参和 按关键字定义(**)的实参
形参里包含 * **
(1)*会将溢出的位置实参全部接收,然后保存成元组的形式赋值给args
1 def foo(x,y,z,*args): #位置 2 print(x,y,z) 3 print(args) ##args=(4,5,6,7,8) 4 5 foo(1,2,3,4,5,6,7,8,)
1 def foo(x,y,z,**kwargs): #关键字 2 print(x,y,z) 3 print(kwargs) # kwargs={'c':3,'a':1,'b':2} 4 5 foo(x=1,y=2,z=3,a=1,b=2,c=3)
(1)一旦碰到实参加*,就把该实参的值打散
1 def foo(x,y,z,*args): 2 print(x,y,z) #1,2,3, 3 print(args) #args=([4,5,6,7,8],) 4 5 foo(1,2,3,*[4,5,6,7,8]) #foo(1,2,3,4,5,6,7,8) #把*里面的打散 6 foo(1,2,3,*(4,5,6,7,8)) #foo(1,2,3,4,5,6,7,8) 7 foo(1,2,3,*'hello') #foo(1,2,3,'h','e','l','l','o')
1 def foo(x,y,z): 2 print(x,y,z) 3 4 foo(*[1,2,3]) #foo(1,2,3) 5 foo(*[1,2,3,4]) #foo(1,2,3,4) 多了一个 报错 6 foo(*[1,2,]) #foo(1,2,) 少了一个 报错
1 def foo(x,y,z,**kwargs): 2 print(x,y,z) 3 print(kwargs) 4 5 foo(1,2,3,**{'a':1,'b':2}) #foo(1,2,3,b=2,a=1) 6 #把**里的打散 7 8 def foo(x,y,z): 9 print(x,y,z) 10 11 foo(1,**{'z':3,'y':2}) #foo(1,z=3,y=2) 12 foo(1,**{'z':3,'y':2,'x':111}) #foo(1,z=3,y=2,x=111) 13 #重复传值 x ,报错
(3)组合使用
1 def index(name,age,gender): 2 print('welcome %s %s %s' %(name,age,gender) 3 4 #---------------------------------------------------- 5 6 def wrapper(*args,**kwargs): #args=(1,2,3),kwargs={'x':1,'y':2,'z':3} 7 index(*args,**kwargs) #index(*(1,2,3),**{'x':1,'y':2,'z':3}) # index(1,2,3,z=3,y=2,x=2) 8 wrapper(1,2,3,x=1,y=2,z=3) 9 #如果这样写,符合了wrapper,但rapper里面有一个index,不符合,报错 10 #在index里面会把元组和集合打散,变成6个元素,而index里面只有3个 11 12 #---------------------------------------------------- 13 14 wrapper(name='egon',age=18,gender='male') #这种写法都可以,符合index的语法 15 wrapper('egon',age=18,gender='male') 16 wrapper('egon',18,gender='male') 17 wrapper('egon',18,'male')
6、命名关键字参数
1 def auth(*args,**kwargs): 2 """ 3 使用方式auth(name="egon",pwd="123") 4 :param args: 5 :param kwargs: 6 :return: 7 """ 8 # print(args,kwargs) 9 if len(args) !=0: 10 print('必须用关键字的形式传参') 11 return 12 if 'name' not in kwargs: 13 print('必须用指定的key名name') 14 return 15 16 if 'pwd' not in kwargs: 17 print('必须用指定的key名pwd') 18 return 19 20 name=kwargs['name'] 21 pwd=kwargs['pwd'] 22 print(name,pwd) 23 24 ef auth(*args,name,pwd): 25 print(name,pwd)