形参与实参 形参即形式参数,就是在定义函数时括号中指定的参数,本质就是一个名字 实参即实际参数,指的是在调用函数的时候传入的参数,是一个实际的值 在调用函数时就会自动把形参(变量名)和实参(值)进行绑定 函数调用结束之后绑定关系就解除了 def func1(a,b):#a,b就是形参 a=1,b=2 print(a) print(b) func1(1,2)#1,2就是实参 位置参数 根据调用阶段 参数分为两类 形参和实参 所以对应的位置参数也有位置形参和位置实参 位置,其实指的是顺序,从左往右来定义的参数就是位置(顺序)参数 需要注意的是: 位置形参的数量与位置实参的数量必须一致,不能多传,也不能少传 实参会按照传入的位置一次赋值给形参 位置形参 位置实参 def func(a,b,c):#abc都是位置形参 print(a,b,c) func(1,2,3)#1,2,3都是位置实参 def register(name,password,sex): print('mynameis% my passwordis%my age is%') %(name,password,sex) register('rose','123','woman') 关键字参数 关键字实参 在调用函数时,指名道姓的为形参赋值就称为关键字参数 其优点是: 可以打破传入蚕食的顺序 可以不与形参顺序相同 注意: 1.不管以什么样的方式传值,每一个形参都必须被传值 2.关键字参数必须位于未知参数的后面 3.不能为同一个参数传多次值 4.使用关键字传参时,实参的名字必须与形参的名字匹配 到底是位置参数还是关键字参数 由实参决定 def func(a,b,c): print(a) print(b) print(c) #func(1,2,c=3)与位置参数没区别 #func(c=1,2,3)语法错误 关键字参数出现在了未知参数前面 #func(a=1,b=2,c=3) 可以打破位置参数的顺序限制 def register(name,pwd): print('name is',name) print('password is',pwd) register(pwd='123',name='bgon') 可以不用完全按照顺序来传值 open ('今日内容',encoding='utf-8') 默认形参 在定义时,就已经为形参制定了一个值,那这个形参就称之为默认形参 特点: 在调用时,可以不用为默认形参传值,这样在函数体中使用默认形参时,使用时就是默认值 当然也可以传值,这样的话内部使用的就是你传入的值 使用场景: 当函数中的某一形参经常出现重复的值时,就可以将其定义为默认形参 可以简化调用代码 需要注意 1.默认形参必须放在非默认形参后面 2.默认形参的值在定义时就已经固定了 3.不应该将默认形参的默认值设置为一个可变类型 会导致 每次函数调用都共用同一个默认参数,我们应该将函数设计为一个独立的功能,每次调用互不干扰 只能是int float str tuple def reg1(name,sex,hobby=['play','music']): print(name,sex) print(hobby) reg1('bgon','man',['play','music','movie']) reg1('cgon','man',['music','sleep']) def reg1(name,sex,hobby): print(name,sex) print(hobby) reg1('bgon','man',['play','music','movie']) reg1('cgon','man',['music','sleep']) 可变长参数指的是,可以传任意个数的实参 传入实参是为了给形参来使用,那就意味着,必须让形参也具备可以接受任意个数的参数的能力 也就是*和** 带*的形参 带*的形参表示可以接受任意个数的实参,这些接受到的实参会被打包成元组类型 形参的名字可以随意,但是建议用args 是arguments的缩写 iterable 可迭代的 只要是可以被for in 循环使用的都是可迭代 字符串 列表 元组 字典 集合 带*的实参 在实参前面加*,会自动将*后的值,打散('abc'打散 成了'a','b','c') 带*的实参 不能接受关键字的实参 def func(*abc): print(abc) pass func(1) func(1,2) func(1,2,3) 位置形参与可变长形参混合使用*** 当可变长形参,出现在了位置形参的前面时,那么后面的位置形参必须以关键字实参来传入 def func(*args,a,b): print(a,b,args) func(1,2,3,a=4,b=5) 当可变长形参出现在位置形参后面,会先按照顺序给前面的位置形参赋值,最后剩余的就赋值给可变长args def func(a,b,*args): print(a,b,args) func(1,2,3,4,5) **的使用 形参中如果带有**,会把关键字实参打包成字典类型传入 只能接收多出来的关键字实参 **不能接受位置实参 def func(**b): print(b) func(1) 先为前面的位置形参赋值,后续的多余的关键字参数赋值给** def func(a,c,**b): print(a,c) print(b) func(1,s=100,c='abc') 实参中带**,会把**后的字典(也必须是字典类型)打散,成关键字实参(**{'a':1}) 打散为a=1 def func(name,sex): print(name,sex) func(**{'name':'rose",'sex':'woman'})#func(name='rose') # print(**{'name':'rose"}) 错误 *和**可以为函数预留扩展空间,后期可以根据需求增加参数,而且旧的函数调用方式也不会出现问题 简单的说就是提高函数的扩展性 写一个带有可变长的位置形参函数 def func(name,pwd,*kwargs) #****** if name == 'bgon' and pwd =='123': if 'phone' in kwargs: if kwargs['phone']=='110' print('登陆成功!') else: print('传入手机号验证!') else: print('登录失败!') func('bgon','123',phone='110') # 该方式可以接受任意个数的位置实参和关键字实参, # 但要注意顺序,位置实参必须在关键字之前 def inner(name,sex,age): print(name,sex,age) def outer(*args,**kwargs): print(args) print(kwargs) inner(*args,**kwargs) # inner(1,2,3,a=10,b=20) outer(1,2,3,100,a=10,b=20) # 上述写法 可以将outer接收到的所有参数 原模原样的传给inner函数