装饰器不能修改被装饰的函数的源代码和调式方法,从而起到装饰这个函数的作用。
比如,有一个函数,在不修改它的情况下得到它的运行时间。
#-*- coding:utf-8 -*- ''' @auther: Starry @file: decorator1.py @time: 2018/1/18 23:11 ''' import time def timer(func): def deco(): start_time = time.time() func() end_time = time.time() print('the func run time is %s'%(end_time - start_time)) return deco @timer #test1 = timer(test1) def test1(): time.sleep(3) print('in the test1!') test1()
使用装饰器 timer 来装饰test1函数。从而得到它的运行时间。
上面只是简单的装饰,当被装饰的函数有参数时该怎么办呢?
在装饰器函数timer里,就需要把参数传进去了。
#-*- coding:utf-8 -*- ''' @auther: Starry @file: decorator2.py @time: 2018/1/18 23:31 ''' import time def timer(func): def deco(*args,**kwargs): start_time = time.time() func(*args,**kwargs) end_time = time.time() print('the func run time is %s'%(end_time - start_time)) return deco @timer def test2(name): print("name:"+name) test2('Starry')
被装饰的函数有参数解决了,但又有一种情况了,当调用装饰器timer去装饰某个函数时,如果装饰器也有参数呢? 比如
@auth(auth_type='local')
@auth(auth_type='ldap')
使用不同的参数来使的调用的方式不同,这使用在装饰器里可以通过加一层函数来解决。
#-*- coding:utf-8 -*- ''' @auther: Starry @file: decorator3.py @time: 2018/1/18 23:33 ''' username, password = 'starry','sky' def auth(auth_type): print('auth func:',auth_type) def wrapper(func): def deco(*args, **kwargs): print('wrapper func:', *args, **kwargs) if auth_type == 'local': user = input('please input your username:') passwd = input('please input your password:') if user == username and password == passwd: print(' 33[32;1mUser has passed authentication 33[0m') return func(*args, **kwargs) else: print(' 33[31;1mInvalid username or password 33[0m') elif auth_type == 'ldap': print('服务器端验证') return deco return wrapper def index(): print('welcome to index page') @auth(auth_type='local') def home(): print('welcome to home page') return 'from home' @auth(auth_type='ldap') def bbs(): print('welcome to bbs page') index() print(home()) bbs()
函数里嵌套函数,嵌套了两次,第一个函数是把装饰器timer里的参数传进去,第二个函数将被装饰的函数当成参数传入,第三个函数是把被装饰的函数里的参数传入。
装饰器的常见三种使用就是这样了。