装饰器
装饰器
1、定义:假设我们要增强一个函数的功能,比如,在函数调用前后自动打印日志,但又不希望改变这个函数的源代码,这种在代码运行期间动态增加功能且又不改变源代码的方式,成为装饰器(Decorator)。本质上,decorator就是一个返回函数的高阶函数
2.实例
如上图中的原函数为index(),我们通过装饰器为其增加了一个计算运行时间的功能,但是没有改变源代码,这就是为其增加了一个装饰器,装饰器的功能就是计时。
关键点:@的语法,@timmer等同于进行了如下操作:index=timmer(index),函数名+()就是调用函数,一定要记住!!好多地方想不通原因就是在这里!
思想就是把部内函数func()换成被装饰函数index()然后再运行闭包函数就好了(可能说的有点简单)
3、给认证装饰器增加一个登陆后再次调用是免认证的功能(字典,只在内存中能行)
import time current_login = {'name': None, 'login': False} # 建立一个字典,字典存储登录状态 def timmer(func): def wrapper(): start_time = time.time() func() stop_time = time.time() print('run time is %s' % (stop_time - start_time)) return wrapper def auth2(auth_type='file'): def auth(func): def wrapper(*args, **kwargs): if current_login['name'] and current_login['login']: # 判断状态是否被激活,若激活直接执行函数结束 res = func(*args, **kwargs) return res if auth_type == 'file': name = input('username:') password = input('password:') if name == 'zhejiangF4' and password == 'sb945': print('auth successful') res = func(*args, **kwargs) current_login['name'] = name # 存储登录状态 current_login['login'] = True return res else: print('auth error') elif auth_type == "sql": print("haibuhui") return wrapper return auth @timmer @auth2(auth_type="file") def index(): print('welcome to index page') @auth2("file") def home(): print("welcome to home page") index() home() # 第一次执行index()函数是需要登录认证,但第二次执行home时就不需要再认证了
4.帮助信息
import time def timmer(func): def wrapper(*args,**kwargs): 'ssssss' start_time=time.time() func(*args,**kwargs) #home(name) stop_time=time.time() print('run time is %s' %(stop_time-start_time)) return wrapper @timmer def func(x): 'fun test' print(x) func(1) print(func.__doc__) ###输出wrapper帮助信息 #print(help(func)) # import time # from functools import wraps # def timmer(func): # @wraps(func) # def wrapper(*args,**kwargs): # 'ssssss' # start_time=time.time() # func(*args,**kwargs) #home(name) # stop_time=time.time() # print('run time is %s' %(stop_time-start_time)) # return wrapper # # @timmer # def func(x): # 'fun test' # print(x) # # func(1) # print(func.__doc__) ###输出wrapper帮助信息 # #print(help(func)) #输出func帮助信息
import time from functools import wraps#从函数工具中调用wraps模块 def timmer(func): @wraps(func)#它就可以让你打印出的index.__doc__编程原函数的"dashabi"而不是wrapper函数的"000" def wrapper(*args,**kwargs): '000' start_time=time.time() res=func(*args,**kwargs) stop_time=time.time() print('run time is %s'%(stop_time-start_time)) return res return wrapper @timmer def index(): "dashabi" print("from index") index() print(index.__doc__)
1 import time #1 2 def timmer(func): #func的值是home的 #3 3 def wrapper(name): #4 #7 #闭包函数 4 print(func) #8 5 start_time=time.time() #9 6 func(name) #home(name) #10 7 stop_time=time.time() #14 8 print('run time is %s' %(stop_time-start_time)) #15 9 return wrapper #5 10 @timmer #home=timmer(home) #2 #6 11 def home(name): #11 12 time.sleep(2) #12 13 print('welcome to %s home page' %name) #13 14 home('dragon') #wrapper('dragon') 15 16 17 <function home at 0x0000000000D0E1E0> 18 welcome to dragon home page 19 run time is 2.0001142024993896