一 函数对象 一 函数是第一类对象,即函数可以当作数据传递 二 利用该特性,优雅的取代多分支的if 1 2 3 4 5 6 7 8 9 10 11 12 13 14 def foo (): print ('foo' ) def bar (): print ('bar' ) dic={ 'foo' :foo, 'bar' :bar, } while True : choice=input ('>>: ' ).strip() if choice in dic: dic[choice]()
二 函数嵌套 一 函数的嵌套调用 1 2 3 4 5 6 7 8 9 def max (x,y ): return x if x > y else y def max4 (a,b,c,d ): res1=max (a,b) res2=max (res1,c) res3=max (res2,d) return res3 print (max4(1 ,2 ,3 ,4 ))
二 函数的嵌套定义 1 2 3 4 5 6 7 8 9 def f1 (): def f2 (): def f3 (): print ('from f3' ) f3() f2() f1() f3()
三 名称空间与作用域 一 什么是名称空间? 二 名称空间的加载顺序 三 名字的查找顺序 1 2 3 4 5 6 7 8 9 10 11 12 13 局部名称空间--->全局名称空间--->内置名称空间 def f1 (): def f2 (): print (max ) f2() f1() print (max )
四 作用域 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 - 全局范围(内置名称空间与全局名称空间属于该范围):全局存活,全局有效 - 局部范围(局部名称空间属于该范围):临时存活,局部有效 x=1 def f1 (): def f2 (): print (x) return f2 x=100 def f3 (func ): x=2 func() x=10000 f3(f1()) LEGB 代表名字查找顺序: locals -> enclosing function -> globals -> __builtins__ locals 是函数内的名字空间,包括局部变量和形参enclosing 外部嵌套函数的名字空间(闭包中常见) globals 全局变量,函数定义所在模块的名字空间builtins 内置模块的名字空间
五 global与nonlocal关键字 关键字global Python里只有2种作用域:全局作用域和局部作用域。全局作用域是指当前代码所在模块的作用域,局部作用域是指当前函数或方法所在的作用域。局部作用域里的代码可以读外部作用域(包括全局作用域)里的变量,但不能更改它。如果想更改它,这里就要使用global关键字了
关键字nonlocal 在Python 2.x
中,闭包只能读外部函数的变量,而不能改写它。为了解决这个问题,Python 3.x
引入了nonlocal关键字,在闭包内用nonlocal声明变量,就可以让解释器在外层函数中查找变量名。
注意:关键字nonlocal:是python3.X
中出现的,所以在python2.x
中无法直接使用.
实例 关键字nonlocal的作用与关键字global类似,使用nonlocal关键字可以在一个嵌套的函数中修改嵌套作用域中的变量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 name = 'pythontab' def func (): global name name = 'pythontab.com' func() print (name) def foo (): name= 'pythontab.com' nonlocal name foo() count = 1 def a (): count = 'a函数里面' def b (): nonlocal count print (count) count = 2 b() print (count) if __name__ == '__main__' : a() print (count)
总结 主要区别有以下两点:
两者的功能不同。global关键字修饰变量后标识该变量是全局变量,对该变量进行修改就是修改全局变量,而nonlocal关键字修饰变量后标识该变量是上一级函数中的局部变量,如果上一级函数中不存在该局部变量,nonlocal位置会发生错误(最上层的函数使用nonlocal修饰变量必定会报错)。
两者使用的范围不同。global关键字可以用在任何地方,包括最上层函数中和嵌套函数中,即使之前未定义该变量,global修饰后也可以直接使用,而nonlocal关键字只能用于嵌套函数中,并且外层函数中定义了相应的局部变量,否则会发生错误。
四 闭包函数 一 什么是闭包? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 def counter (): n=0 def incr (): nonlocal n x=n n+=1 return x return incr c=counter() print (c()) print (c()) print (c()) print (c.__closure__[0 ].cell_contents)
二 闭包的意义与应用 1 2 3 4 5 6 7 8 9 10 11 from urllib.request import urlopen def index (url ): def get (): return urlopen(url).read() return get baidu=index('http://www.baidu.com' ) print (baidu().decode('utf-8' ))
五 装饰器 装饰器就是闭包函数的一种应用场景。
为什么要用装饰器 1 2 3 4 5 6 7 8 9 开放封闭原则: 软件一旦上线,就应该遵循开放封闭原则,即对修改源代码是封闭的,对功能扩展是开放的。 也就是说我们必须找到一种解决方案: 能够在不修改一个功能源代码以及调用方式的前提下,为其添加新功能 原则如下: 1 、不修改源代码 2 、不修改调用方式 装饰器目的: 在遵循1 和2 原则的基础上扩展新功能
什么是装饰器 装饰他人的器具:本身可以是任意可调用对象,被装饰者也可以是任意可调用对象
强调-装饰器的原则:1、不修改被装饰对象的源代码;2、不修改被装饰对象的调用方式
装饰器的目标:在遵循1和2的前提下,为被装饰对象添加新功能
装饰器的使用 无参装饰器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 import timedef home (name ): time.sleep(3 ) print ("Welcome {} to moyan blog" .format (name)) home('allen' ) def home (name ): startTime=time.time() time.sleep(3 ) print ("Welcome {} to moyan blog" .format (name)) stopTime=time.time() print ('home time {}' .format (stopTime-startTime)) home('allen' ) def home (name ): time.sleep(3 ) print ("Welcome {} to moyan blog" .format (name)) startTime=time.time() home('allen' ) stopTime = time.time() print ('home time {}' .format (stopTime - startTime))def home (name ): time.sleep(3 ) print ("Welcome {} to moyan blog" .format (name)) def wrapper (func ): startTime = time.time() func('allen' ) stopTime = time.time() print ('home time {}' .format (stopTime - startTime)) wrapper(home) def home (name ): time.sleep(3 ) print ("Welcome {} to moyan blog" .format (name)) def outter (func ): def wrapper (): startTime = time.time() func('allen' ) stopTime = time.time() print ('home time {}' .format (stopTime - startTime)) return wrapper home=outter(home) home() import timedef outter (func ): def wrapper (): startTime = time.time() func('allen' ) stopTime = time.time() print ('home time {}' .format (stopTime - startTime)) return wrapper @outter def home (name ): time.sleep(3 ) print ("Welcome {} to moyan blog" .format (name)) home()
被装饰对象无参+返回值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import timedef outter (func ): def wrapper (): startTime = time.time() fee=func('allen' ) stopTime = time.time() print ('home time {}' .format (stopTime - startTime)) return fee return wrapper @outter def home (name ): time.sleep(3 ) print ("Welcome {} to moyan blog" .format (name)) return 123 res=home() print (res)
被装饰对象有参+返回值 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import timedef outter (func ): def wrapper (name ): startTime = time.time() fee=func(name) stopTime = time.time() print ('home time {}' .format (stopTime - startTime)) return fee return wrapper @outter def home (name ): time.sleep(3 ) print ("Welcome {} to moyan blog" .format (name)) return 123 res=home('allen' ) print (res)
装饰多个对象 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 import timedef outter (func ): def wrapper (name ): startTime = time.time() fee=func(name) stopTime = time.time() print ('home time {}' .format (stopTime - startTime)) return fee return wrapper @outter def home (name ): time.sleep(3 ) print ("Welcome {} to moyan blog" .format (name)) return 123 @outter def index (): time.sleep(1 ) print ('test ok' ) home('allen' ) index() import timedef outter (func ): def wrapper (*args,**kwargs ): startTime = time.time() fee=func(*args,**kwargs) stopTime = time.time() print ('home time {}' .format (stopTime - startTime)) return fee return wrapper @outter def home (name ): time.sleep(3 ) print ("Welcome {} to moyan blog" .format (name)) return 123 @outter def index (): time.sleep(1 ) print ('test ok' ) home('allen' ) index()
简单写的认证装饰器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 name_ok={ 'name' :None , } def outer (func ): def inner (*args,**kwargs ): if name_ok['name' ]: res = func(name_ok['name' ]) return res name = input ('input username: ' ) passwd = input ('input passwd: ' ) if name=='allen' and passwd=='123' : print ('登录成功!' ) name_ok['name' ]=name res = func(*args, **kwargs) return res else : print ('name or passwd ERROR' ) return inner @outer def index (): print ('欢迎!!!' ) @outer def home (*args,**kwargs ): print ('welcome {} to home' .format (*args,**kwargs)) return 123 index() home()
叠加多个装饰器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 name_ok={ 'name' :None , } def outer (func ): def inner (*args,**kwargs ): if name_ok['name' ]: res = func(name_ok['name' ]) return res name = input ('input username: ' ) passwd = input ('input passwd: ' ) if name=='allen' and passwd=='123' : print ('登录成功!' ) name_ok['name' ]=name res = func(*args, **kwargs) return res else : print ('name or passwd ERROR' ) return inner import timedef timemer (func ): def inner (*args,**kwargs ): startTime = time.time() res=func(*args,**kwargs) stopTime = time.time() print (stopTime-startTime) return res return inner @outer @timemer def index (): time.sleep(1 ) print ('欢迎!!!' ) @timemer @outer def home (*args,**kwargs ): time.sleep(2 ) print ('welcome {} to home' .format (*args,**kwargs)) return 123 index() home()
有参装饰器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 name_ok={ 'name' :None , } def auth (engine ): def auth2 (func ): def inner (*args,**kwargs ): if engine == 'file' : print ('基于file认证' ) if name_ok['name' ]: res = func(name_ok['name' ]) return res name = input ('input username: ' ) passwd = input ('input passwd: ' ) if name=='allen' and passwd=='123' : print ('登录成功!' ) name_ok['name' ]=name res = func(*args, **kwargs) return res else : print ('name or passwd ERROR' ) elif engine =='mysql' : print ('基于mysql认证' ) elif engine =='ldap' : print ('基于ldap认证' ) return inner return auth2 @auth('mysql' ) def home (): print ('welcome to home' ) return 123 home()
装饰器总结 1 2 3 4 5 6 7 8 def outer (func ): def inner (*args,**kwargs ): res=func(*args,**kwargs) return res return inner
装饰器补充:wraps 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from functools import wrapsdef deco (func ): @wraps(func ) def wrapper (*args,**kwargs ): return func(*args,**kwargs) return wrapper @deco def index (): '''哈哈哈哈''' print ('from index' ) print (index.__doc__) print (index.__doc__)