python装饰器
一,python的装饰器是什么?
二,python装饰器
三,带有参数的装饰器
一,python的装饰器是什么?
python装饰器其实就是一个函数,它用于给其他函数添加一些新功能。这个就是python的装饰器。
二,python的装饰器
1,python装饰器的原则
a,不修改被装饰的函数的原代码
b,不修改原函数的调用方式
归纳一下其实就是装饰器对待被修饰的函数完全是透明,是感知不到装饰器的存在的。
基于以上2点给被装饰的函数添加新功能。
2,python装饰器的基本知识
a,函数即变量
b,高阶函数
c,嵌套函数
d,高阶函数+嵌套函数==》装饰器
a,函数即变量
a = 1 把内存比喻酒店的话,那么就会有间房存放1,然后存放1的房间门牌号就是a.
b = a 这个其实就是给存放1的房间多添加一个门牌号。
那么python是有垃圾回收的机制,那么怎样的情况下,才会回收1呢?
只要存放1的房间号没有门牌号,即没有函数名,那么这个1就会立马被回收。如果人为的回收,可以使用del命令即可。
那么函数和变量是一样的。比如
def test():
pass
把test作为门牌号,函数体的内容放到房间里面
当然,匿名函数也是一样的道理。如下图
上面函数即变量的意思,其实就是你定义一个函数,其实当Python解释器执行到def 的时候并不会执行这个代码块,其实就是和存放变量一样,存放一下仅此而已。
b,高阶函数
高阶函数满足一下任一条件,即为高阶函数。
1,把一个函数名当做实参传给另外一个函数(在不修改被装饰函数的源代码的情况下为其他添加新功能)
2, 返回值中包含函数名(不修改函数的调用方式)
def a(): print('in the a') def b(a): pass b()
像这种就算是高阶函数的一种,符合第一个条件。
如果想要符合第二个条件,只要函数return a 就可以满足第二个条件了。
c,函数的嵌套
1,这个是函数的调用
def test1(): print('in the test1') def test2(): test1() test2()
2,这个是函数的嵌套
def test1(): def test2(): print('in the test2') test1()
d,高阶函数 + 嵌套函数 = 装饰器
如下是个简单的装饰器:
import time def timmer(func): def wrapper(): start_time = time.time() func() stop_time = time.time() print('the func run time is {0}'.format(stop_time-start_time)) return wrapper def bar(): time.sleep(2) print('in the bar') bar = timmer(bar)
可以发现,这个装饰是由高级函数和嵌套函数组成的。
这个装饰器的功能就是给函数添加运行时间的功能。其实上面的bar = timmer(bar)可以使用python提供的语法糖来写那么就更简单了。
import time def timmer(func): def wrapper(): start_time = time.time() func() stop_time = time.time() print('the func run time is {0}'.format(stop_time-start_time)) return wrapper @timmer def bar(): time.sleep(2) print('in the bar') #bar = timmer(bar)
这样一个装饰器就完成了。从这个简单的装饰器来看。我们可以发现当我们调用bar()这个函数的时候不仅仅是返回了函数的内容,而且还只能加了计算时间的功能。
仔细一看 但我们调用bar()的时候,我们可以发现其实我们调用的是wrapper这个函数,因为timmer这个函数是return wrapper这个函数地址,所以bar = wrapper ,那么咱们调用的时候
bar()其实就是等于wrapper()。
上面的简单完成了装饰器的功能,如果想把这个装饰器用于其他函数,只需在其他函数上面添加@timmer即可装饰其他函数(前提其他函数是没有参数的)
为了是上面的装饰器可以装饰其他函数,比如函数自带参数.所以咱们需要把上面的函数简单修改一下。
import time def timmer(func): def wrapper(*args,**kwargs): start_time = time.time() func(*args,**kwargs) stop_time = time.time() print('the func run time is {0}'.format(stop_time-start_time)) return wrapper @timmer def bar():
print('in the bar') @timmer def test(name): print ('my name is {0}'.format(name)) bar() test()
为了能够是装饰器可以装饰其他函数,将传入的参数设置成冗余。所以即使test有变量,也不会影响它的装饰的功能。
上面讲到了bar = wrapper 同理 test=wrapper 所以如果test函数是需要传入参数的话,毫无疑问wrapper也是需要设置形参的。为了防止传入的参数不定,所以用*args和**kwargs来代替。当然这里传入的参数也需要使用*args和**kwargs
还有一种就是要装饰的函数是带有return值的,所以装饰器要简单改一下,即装饰器里面接受一下赋值给一个变量,然后输出。
import time def timmer(func): def wrapper(): start_time = time.time() result = func() print(result) stop_time = time.time() print('the func run time is {0}'.format(stop_time-start_time)) return wrapper @timmer def bar(): time.sleep(2) print('in the bar') return 'from bar' bar()
三,带有参数的装饰器
#!/usr/bin/env python # -*- conding:utf-8 -*- import time user,passwd = 'test','test123' def auth(auth_type): def outer_wrapper(func): def wrapper(*args,**kwargs): username = input('username:').strip() password = input('password:').strip() if auth_type == 'local': if user==username and passwd==password: print('登录成功!') res = func(*args,**kwargs) return res else: print('登录失败') elif auth_type == 'ladp': print('ladp正在建设中!') return wrapper return outer_wrapper def index(): print('welcome to index page') @auth(auth_type='local') # a= auth(参数) home = a(home) def home(): print('welcome to home page') return 'from home' @auth(auth_type='ladp') def bbs(): print('welcome to bbs page') index() print (home()) bbs()