一、为什么要用函数
#1、代码的组织结构不清晰,可读性差 #2、遇到重复的功能只能重复编写实现代码,代码冗余 #3、功能需要扩展时,需要找出所有实现该功能的地方修改之,无法统一管理且维护难度极大
二、函数是什么
想象生活中的例子,修理工需要实现准备好工具箱里面放好锤子,扳手,钳子等工具,然后遇到锤钉子的场景,拿来锤子用就可以,而无需临时再制造一把锤子。 修理工===>程序员 具备某一功能的工具===>函数 要想使用工具,需要事先准备好,然后拿来就用且可以重复使用 要想用函数,需要先定义,再使用
三、函数的分类
#1、内置函数 为了方便我们的开发,针对一些简单的功能,python解释器已经为我们定义好了的函数即内置函数。对于内置函数,我们可以拿来就用而无需事先定义,如len(),sum(),max() #2、自定义函数 很明显内置函数所能提供的功能是有限的,这就需要我们自己根据需求,事先定制好我们自己的函数来实现某种功能,以后,在遇到应用场景时,调用自定义的函数即可。
四、如何定义一个函数
#语法 def 函数名(参数1,参数2,参数3,...): '''注释''' 函数体 return 返回的值 #函数名要能反映其意义
4.1 实操
def tell_tag(): print('===========') def tell_msg(msg): print(msg) #调用阶段 tell_tag() tell_tag() tell_msg('hello world') tell_tag() tell_tag() # func() print(tell_msg) ''' =========== =========== hello world =========== =========== '''
五、函数使用的原则:先定义,再调用
5.1 实操
#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()
六、函数在定义阶段都干了哪些事
#只检测语法,不执行代码 也就说,语法错误在函数定义阶段就会检测出来,而代码的逻辑错误只有在执行时才会知道
6.1 实操
#函数在定义阶段,只检测语法,不执行代码 def func(): print('aaaaaa') xxxxx yyyy zzssaa asdfasdfasdfasdf # if # print('asdfasdfasfd' func()
七、定义函数的三种形式
#1、无参:应用场景仅仅只是执行一些操作,比如与用户交互,打印 #2、有参:需要根据外部传进来的参数,才能执行相应的逻辑,比如统计长度,求最大值最小值 #3、空函数:设计代码结构
#结论: #1、定义时无参,意味着调用时也无需传入参数 #2、定义时有参,意味着调用时则必须传入参数
八、调用函数
函数的调用:函数名加括号 1 先找到名字 2 根据名字调用代码
8.1 函数返回值
无return->None return 1个值->返回1个值 return 逗号分隔多个值->元组 什么时候该有返回值? 调用函数,经过一系列的操作,最后要拿到一个明确的结果,则必须要有返回值 通常有参函数需要有返回值,输入参数,经过计算,得到一个最终的结果 什么时候不需要有返回值? 调用函数,仅仅只是执行一系列的操作,最后不需要得到什么结果,则无需有返回值 通常无参函数不需要有返回值
8.2 实操
#1 调用函数:函数名(), #需要注意:先通过名字找到函数的内存地址,然后加括号调用 #2 函数的返回值return #注意的第一点: #在调用函数的过程中,一旦执行到return,就会立刻终止函数,并且把return后的结果当做本次调用的返回值返回 #函数体内可以有多个return,但是只能执行一次 # def foo(): # print('111') # return 1 # print('2222') # return 2 # print('3333') # return 3 # # res=foo() # print('函数调用完毕',res) #注意的第二点: #返回的值,可以是任意类型 #注意的第三点: #没有return:默认返回None #可以返回一个值===>值 #可以用逗号分隔,返回多个值===>tuple # def foo(): # return None # # res=foo() # print('函数调用完毕',res,type(res)) #3:调用函数的三种形式 def foo(): print('from foo') return 123 # foo() # res=foo() # print(res) res=foo()*10 print(res)
九、函数的参数
形参与实参
#形参即变量名,实参即变量值,函数调用时,将值绑定到变量名上,函数调用结束,解除绑定
9.1 实操
#形参:在定义函数时,括号内的参数成为形参 #特点:形参就是变量名 # def foo(x,y): #x=1,y=2 # print(x) # print(y) #实参:在调用函数时,括号内的参数成为实参 #特点:实参就是变量值 # foo(1,2) #在调用阶段实参(变量值)才会绑定形参(变量名) #调用结束后,解除绑定 #参数的分类 #位置参数:按照从左到右的顺序依次定义的参数 #位置形参:必须被传值,并且多一个不行,少一个也不行 #位置实参:与形参按照位置一一对应 # def foo(x,y): # print(x) # print(y) # # foo('egon',1,2) #关键字实参:指的是按照name=value的形式,指名道姓地给name传值 # def foo(name,age): # print(name) # print(age) # foo('egon',18) # foo(age=18,name='egon') #关键字实参需要注意的问题是: # def foo(name,age,sex): # print(name) # print(age) # print(sex) # foo('egon',18,'male') # print('======>') # foo(sex='male',age=18,name='egon') # foo('egon',sex='male',age=18) #问题一:语法规定位置实参必须在关键字实参的前面 # foo('egon',sex='male',age=18) #问题二:一定不要对同一个形参传多次值 # foo('egon',sex='male',age=18,name='egon1') # foo('male',age=18,name='egon1') #默认形参:在定义阶段,就已经为形参赋值,意味在调用阶段可以不用传值 # def foo(x,y=1111111): # print(x) # print(y) # # foo(1,'a') # # def register(name,age,sex='male'): # print(name,age,sex) # # register('asb',73) # register('wsb',38) # register('ysb',84) # register('yaya',28,'female') #默认参数需要注意的问题 #问题一:默认参数必须放在位置参数之后 # def foo(y=1,x): # print(x,y) #问题二:默认参数只在定义阶段赋值一次,而且仅一次 # x=100 # def foo(a,b=x): # print(a,b) # # x=111111111111111111111111111111 # foo('egon') #问题三:默认参数的值应该定义成不可变类型
9.2 具体应用
#1、位置参数:按照从左到右的顺序定义的参数 位置形参:必选参数 位置实参:按照位置给形参传值 #2、关键字参数:按照key=value的形式定义的实参 无需按照位置为形参传值 注意的问题: 1. 关键字实参必须在位置实参右面 2. 对同一个形参不能重复传值 #3、默认参数:形参在定义时就已经为其赋值 可以传值也可以不传值,经常需要变得参数定义成位置形参,变化较小的参数定义成默认参数(形参) 注意的问题: 1. 只在定义时赋值一次 2. 默认参数的定义应该在位置形参右面 3. 默认参数通常应该定义成不可变类型 #4、可变长参数: 可变长指的是实参值的个数不固定 而实参有按位置和按关键字两种形式定义,针对这两种形式的可变长,形参对应有两种解决方案来完整地存放它们,分别是*args,**kwargs ===========*args=========== def foo(x,y,*args): print(x,y) print(args) foo(1,2,3,4,5) def foo(x,y,*args): print(x,y) print(args) foo(1,2,*[3,4,5]) def foo(x,y,z): print(x,y,z) foo(*[1,2,3]) ===========**kwargs=========== def foo(x,y,**kwargs): print(x,y) print(kwargs) foo(1,y=2,a=1,b=2,c=3) def foo(x,y,**kwargs): print(x,y) print(kwargs) foo(1,y=2,**{'a':1,'b':2,'c':3}) def foo(x,y,z): print(x,y,z) foo(**{'z':1,'x':2,'y':3}) ===========*args+**kwargs=========== def foo(x,y): print(x,y) def wrapper(*args,**kwargs): print('====>') foo(*args,**kwargs) #5、命名关键字参数:*后定义的参数,必须被传值(有默认值的除外),且必须按照关键字实参的形式传递 可以保证,传入的参数中一定包含某些关键字 def foo(x,y,*args,a=1,b,**kwargs): print(x,y) print(args) print(a) print(b) print(kwargs) foo(1,2,3,4,5,b=3,c=4,d=5) 结果: 1 2 (3, 4, 5) 1 3 {'c': 4, 'd': 5}
9.3 实操
#1:形参与实参 #形参:在函数定义阶段,括号内定义的参数的称为形参,就相当于变量名 #实参:在函数调用阶段,括号内定义的参数的称为实参,就相当于变量值 #在调用阶段,实参的值会绑定给形参,在调用结束后,解除绑定 # def foo(x,y): #x=1,y=2 # print(x,y) # # foo(1,2) #参数的分类: ''' 一:位置参数 位置形参:必须被传值的参数,多一个不行,少一个也不行 位置实参:从左到右依次赋值给形参 ''' # def foo(x,y): # print(x,y) # # foo(1,2) ''' 二:关键字参数:在函数调用阶段,按照key=value的形式定义实参 可以不依赖位置而指名道姓地给形参传值 需要注意的问题(可以与位置实参混用,但是): 1. 位置实参必须在关键字实参的前面 2. 不能为一个形参重传值 ''' # def foo(x,y): # print(x,y) # # foo(1,2,y=20) ''' 三:默认参数:在定义函数阶段,已经为形参赋值了,在定义阶段已经赋值,意味着在调用阶段 可以不传值 注意的问题: 1 默认参数的值,只在定义时赋值一次 2 位置形参应该在默认参数的前面 3 默认参数的值应该是不可变类型 ''' # def foo(x,y=10): # print(x,y) # # # foo(y=11,x=1) # def register(name,age,sex='male'): # print(name,age,sex) # # # register('egon',18) # register('wsb',18) # register('alex',38,'xxxxxx') # x='male' # def register(name,age,sex=x): # print(name,age,sex) # # x='female' # register('alex',18) # # def register(name,sex='male',age): # print(name,age,sex) '''
9.4 实操二
可变长参数 实参可变长度指的是:实参值的个数是不固定 而实参的定义形式无非两种:1、位置实参,2、关键字实参 针对这两种形式的实参个数不固定,相应的,形参也要有两种解决方案 * ** ''' #针对按照位置定义的溢出的那部门实参,形参:*args # def func(x,y,z,*args): #args=(4,5,6) # print(x,y,z) # print(args) # # func(1,2,3) # func(1,2,3,4,5,6) # func(1,2,3,*[4,5,6]) #func(1,2,3,4,5,6) # func(*[1,2,3,4,5,6]) #func(1,2,3,4,5,6) # func([1,2,3,4,5,6]) #func(1,2,3,4,5,6) # def func(x,y,z): # print(x,y,z) # # l=[1,2,3] # func(*l) #针对按照关键字定义的溢出的那部分实参,形参:**kwargs # def foo(x,y,**kwargs): #kwargs={'a':1,'z':3,'b':2} # print(x,y) # print(kwargs) # foo(y=2,x=1,z=3,a=1,b=2) # foo(1,2,3,z=3,a=1,b=2) # foo(y=1,x=2,**{'a':1,'b':2,'c':3}) #foo(x=2,y=1,c=3,b=2,a=1) # foo(**{'x':1,'a':1,'b':2,'c':3}) #foo(x=1,c=3,b=2,a=1) # def foo(x,y,z): # print(x,y,z) # # dic={'x':1,'y':3,'z':1} # foo(**dic) #foo(x=1,y=3,a=1) # # def home(name,age,sex): # print('from home====>',name,age,sex) # # def wrapper(*args,**kwargs): #args=(1,2,3,4,5,6,7),kwargs={'c':3,'b':2,'a':1} # home(*args,**kwargs) # # home(*(1,2,3,4,5,6,7),**{'c':3,'b':2,'a':1}) # #home(1,2,3,4,5,7,a=1,b=2,c=3) # # # # # wrapper(1,2,3,4,5,6,7,a=1,b=2,c=3) # wrapper('egon',sex='male',age=19) #五:命名关键字参数(了解): # 形参中,在*后定义的参数称之为命名关键字参数, # 它的特性是;传值时,必须按照关键字实参的形式传值 # def foo(x,y=20,*args,a=1,b): # print(x,y,a,b) # # foo(10,b=3) # foo(10,22,33,44,a=2,b=3) # 位置参数,默认参数,*args,命名关键字参数,**kwargs
十、函数对象
10.1 实操
#函数是第一类对象:函数可以当做数据来使用 def foo(): print('from foo') #可以被引用 # f=foo # # print(f) # f() #可以当做参数传入一个函数 # def wrapper(x): # # print(x) # x() # wrapper(foo) #可以当做函数的返回值 # def wrapper(): # return foo # # f=wrapper() # print(f is foo) #可以当做容器类型的一个元素 # l=[foo,1,2] # l[0]() data_dir='/usr/local/mysql/data' def select(sql): print('select功能: ',sql) def insert(sql): print('insert功能: ', sql) def update(sql): print('update功能: ', sql) def delete(sql): print('delete功能: ', sql) def alter(sql): print('alter功能:',sql) func_dic={ 'select':select, 'update':update, 'insert':insert, 'delete':delete, 'alter':alter } def main(): while True: inp=input('>>: ').strip() if not inp:continue sql=inp.split() cmd=sql[0] # if cmd == 'select': # select(sql) # elif cmd == 'update': # update(sql) # elif cmd == 'insert': # insert(sql) # elif cmd == 'delete': # delete(sql) if cmd in func_dic: func_dic[cmd](sql) else: print('command not found') main()
十一、函数嵌套
11.1 实操
#1 函数的嵌套调用:在调用一个函数的过程中,又调用其他的函数 # def my_max2(x,y): # if x > y: # return x # else: # return y # # # def my_max4(a,b,c,d): # res1=my_max2(a,b) # res2=my_max2(res1,c) # res3=my_max2(res2,d) # return res3 # # res=my_max4(1,2,3,4) # print(res) #2 函数的嵌套定义:在定义一个函数内部,又定义了一个函数 def f1(): def f2(): def f3(): print('from f3') f3() x=1 f2() print(x) f1() # f2() # print(x)