函数
目录:
一、函数的基本概念
1. 什么是函数 具备某一功能的工具->函数 事先准备工具的过程--->函数的定义 遇到应用场景,拿来就用---->函数的调用 函数分类两大类: 1. 内置函数 2. 自定义函数 2. 为何要用函数 1. 代码冗余 2. 可读性差 3. 可扩展性差 3. 如何用函数 原则:必须先定义,再调用 定义函数的语法: def 函数名(参数1,参数2,...): """文档注释""" code1 code2 code3 .... return 返回值 调用函数的语法: 函数名(值1,值2,...)
函数代码实例:
def login(): uname=input('请输入用户名>>: ').strip() pwd=input('password>>: ').strip() if uname == 'egon' and pwd == '123': print('login successfull') return True else: print('user or password error') return False print(login) login()
二、函数的使用原则
函数的使用分为两个明确的阶段:
1.定义阶段:只检测语法,不执行函数体代码
2.调用阶段:会触发函数体代码的执行
原则:先定义,后调用
# 示范一 def foo(): print('from foo') bar() foo() #会报错 # 示范二: def bar(): print('from bar') def foo(): print('from foo') bar() foo() # 示范三: def foo(): print('from foo') bar() def bar(): print('from bar') foo() #示范四: def foo(): print('from foo') bar() foo() #报错,不满足先定义,后调用 def bar(): print('from bar')
三、函数的定义与调用
1、函数定义的三种形式:
# 有参函数 def func(x): .... func(1) # 无参函数 def bar(): .... bar() # 空函数 def func(): pass #没有函数体 func()
2、函数调用的三种形式:
def max2(x,y):
if x > y:
return x
else:
return y
max2() # 语句形式 res=max2(10,20)*12 # 表达式 res=max2(max2(10,20),30) # 将函数的调用当作参数传给另外一个函数 print(res)
四、函数的返回值(return 值)
注意:
1.函数的返回值没有类型限制
2.函数的返回值没有个数限制
2.1返回多个值:多个返回值用逗号分隔开,返回的是元组形式
def func(): print('from func') return 1,1.1,'hello',[1,2,3] res=func() print(res,type(res))
#(1, 1.1, 'hello', [1, 2, 3]) <class 'tuple'>
2.2返回一个值:返回的就是该值本身
def func(): return 123 res=func() print(res,type(res)) #123 <class 'int'>
2.3返回0个值或者干脆没有return:返回None
def func(): return pass res=func() print(res) #None def func(): pass res=func() print(res) #None
3.return除了有返回值的功能,还有结束函数执行的功能(可以结束循环嵌套)
函数内可以有多个return,但只要执行一次,整个函数就会立刻结束,并且将return后的值返回
def func(): print(1) return print(2) return print(3) func()
五、函数参数的使用
一:函数的参数分为两大类:
形式参数(形参):在函数定义阶段,括号内定义的参数/变量名称为形参
实际参数(实参):在函数调用姐夫安,括号内传入的值/变量值称为实参
ps:在调用函数阶段会将实参(值)绑定给形参(变量名),这种绑定关系只在调用函数时生效,在函数执行完后解除绑定
def func(x,y): #x=1 y=2 # x=1 # y=2 print(x,y) func(1,2) print(x) print(y) #报错,x,y没有定义
二:参数的细分:
1.位置参数:
1.1位置形参:在定义阶段,按照从左到右的顺序依次定义的形参称之为位置形参
特点:但凡按照位置定义的形参,必须被传值,多一个不行少一个也不行
def func(x,y,z): print(x,y,z) func(1,2) #报错 func(1,2,3) func(1,2,3,4) #报错
1.2位置实参:在调用阶段,按照从左到右的顺序依次传入的值称之为位置实参
特点:
1.与形参一一对应
def func(x,y,z): print(x,y,z) func(2,1,3)
2.关键字实参:在调用阶段,按照key=value的形式定义的实参称之为关键字实参
特点:可以完全打乱顺序,但仍然能为指定的形参传值(总结:指名道姓的为指定的形参传值)
def func(x,y,z): print(x,y,z) func(x=1,y=2,z=3) func(1,2,3) func(z=3,y=2,x=1)
实参的形式可以是位置实参和关键字实参混合使用,但是必须遵循原则
1.位置实参必须放在关键字实参的前面
2.不能对同一个形参重复传值
func(1,z=3,y=2) func(z=3,1,y=2) #错误 func(1,z=3,x=2,y=3) #错误,对x进行了重复赋值
3.默认形参:在定义阶段,就已经为形参赋值,该形参称之为默认参数
特点:
1.定义阶段已经有值,意味着调用阶段可以不用传值
2.位置形参必须放在默认形参的前面
3.默认形参的值在函数定义阶段就已经固定死了,定义阶段之后的改动不会影响该值
4.默认形参的值通常应该是不可变类型
不是必须赋值
def func(x,y,z=100): print(x,y,z) func(10,20) func(10,20,200)
对于重复进行的操作,如果有一个形参只在少数情况下会改变 def register(name,age,sex='male'): print(name,age,sex) register('egon',18,) register('lxx',38,) register('cw',48,) register('yyh',58,) register('alex',73,'female')
位置形参不能放在默认形参之后 def func(x,z=100,y): print(x,y,z) #报错
默认形参只在定义阶段赋值。 #同级别代码按顺序执行,m会被赋值10:等调用函数的时候会直接进入函数,不会给z重新赋值 m=10 def func(x,y,z=m): #z=10 print(x,y,z) m=100 func(1,2)
每次调用函数生成新的列表
def add_hobby(name,x,hobbies=None): if hobbies is None: hobbies=[] hobbies.append(x) print('%s 的爱好有 %s' %(name,hobbies)) add_hobby('egon','read',) add_hobby('wxx','eat',) add_hobby('alex','piao')
#
egon 的爱好有 ['read']
wxx 的爱好有 ['eat']
alex 的爱好有 ['piao']
4.可变长参数:
可变长实参:指的是在调用阶段,实参值个数是不固定的
实参无非两种形式(位置,关键字实参),对应着形参也必须有两种解决方案分别接收溢出位置实参或关键字实参
*-------->溢出的位置实参
**------->溢出的关键字实参
对位置实参求和 def sum2(*x): #x=(1,2,3,4,5) res=0 for i in x: res+=i return res print(sum2(1,2,3,4,5))
4.1 *的用法
在形参前加*:*会将溢出的位置实参存成元组的形式,然后赋值给*后的形参名
3,4,5均是溢出实参 def func(x,y,*z): #z=(3,4,5) print(x,y,z) func(1,2,3,4,5)
在实参前加*:但凡碰到实参中带*的,先将实参打散成位置实参,再与形参做对应
带*的实参打散后,要与形参进行对应,所以个数要匹配 def func(x,y,z): print(x,y,z) func(1,2,[3,4,5]) func(*[1,2,3,4,5]) #func(1,2,3,4,5),报错 func(*[1,2,3]) #func(1,2,3)
def func(x,y,*z):
print(x,y,z)
func(1111,2222,*[1,2,3,4,5]) #func(1111,2222,1,2,3,4,5)
# 1111 2222 (1, 2, 3, 4, 5) 元组形式
4.2 **的用法
在形参前加**:**会将溢出的关键字实参存成字典的形式,然后赋值给**后的形参名
def func(x,y,**z): #z={'c':3,'b':2,'a':1},无序 print(x,y,z) func(1,y=2,a=1,b=2,c=3)
在实参前加**:但凡碰到实参中带**的,先将实参打散成关键字实参,再与形参做对应
def func(x,y,z): print(x,y,z) func(1,**{'y':2,'z':3}) #func(1,z=3,y=2) func(1,**{'a':2,'y':333,'z':3}) #func(1,a=2,y=333,z=3) # 错误,多一个参数
def func(x,y,**z):
print(x,y,z)
func(**{'y':1,'x':2,'a':1111,'b':2222}) #func(y=1,x=2,a=1111,b=2222)
# 2 1 {'a': 1111, 'b': 2222}
4.3 形参中:*args, **kwargs
def func(x,*args): print(x) print(args) def func(x,**kwargs): print(x) print(kwargs)
4.4 *与**的应用:
def index(name,age,sex): print('index=====>',name,age,sex) index('egon',18,'male')
# 会将wrapper函数接收的参数格式原封不动地转嫁给其内部的index函数,调用时,实参必须要遵循的是index的参数规则
def wrapper(*args,**kwargs): #args=('egon',) kwargs={'sex':'male','age':18}
print(args) print(kwargs)
index(*args,**kwargs) #index(*('egon',),**{'sex':'male','age':18}) #index('egon',sex='male',age=18)
wrapper(1,2,3,4,5,a=1,b=2,c=3) #报错,按照index的参数规则,形参和实参个数对不上
wrapper('egon',sex='male',age=18)
5.命名关键字参数
了解:
命名关键字参数: 在定义函数时,*与**之间参数称之为命名关键字参数 特点: 在调用函数时,命名关键字参数必须按照key=value的形式传值 def func(x,*,y=1,z): print(x) print(y) print(z) func(1,z=2) def func(a,b=2,*args,c,**kwargs): print(a) print(b) print(args) print(c) print(kwargs)