python 基础 —装饰器练习
由于对装饰器不是特别理解,因此做了以下练习,并debug自行理解,在此做一个记录
以下练习均出自菜鸟教程装饰器一章 http://www.runoob.com/w3cnote/python-func-decorators.html
第一个练习
1 from functools import wraps 2 3 def deco_name(f): 4 @wraps(f) 5 def decorated(*args,**kwargs): 6 if not can_run: 7 return "Function will not run" 8 return f(*args,**kwargs) 9 return decorated 10 11 @deco_name #func=deco_name(func) 12 def func(): #执行了deco_name装饰器后返回来了decorated,因此func=decorated 13 return("Function is running") 14 15 can_run =True 16 print(func()) 17 #执行func()相当于执行decorated() 18 # can_run =True,因此decorated()返回func()返回的值:"Function is running" 19 20 can_run =False 21 print(func()) 22 #can_run =False,decorated()进入if选择,返回了"Function will not run"
当使用装饰器装饰一个函数时,函数本身就已经是一个新的函数;即函数名称或属性产生了变化。
在python的functools模块中提供了wraps装饰函数来确保原函数在使用装饰器时不改变自身的函数名及应有属性。
因此在装饰器的编写中建议加入wraps确保被装饰的函数不会因装饰器带来异常情况。
第二个练习
1 from functools import wraps 2 3 def logit(func): 4 @wraps(func) 5 def with_logging(*args, **kwargs): 6 print(func.__name__ + " was called") #addition_func=func ==》输出addition_func_was called 7 return func(*args, **kwargs) #addition_func=func,因此返回addition_func执行的结果 8 9 return with_logging 10 11 12 @logit # addition_func=logit(addition_func=func)返回with_logging ==》addition_func=with_logging 13 def addition_func(x): 14 """Do some math.""" 15 return x + x 16 17 #addition_func(4)= with_logging(4)=func(4) 18 result = addition_func(4) 19 print(result)
第三个练习
带参数的装饰器
1 from functools import wraps 2 def logit(logfile='out.log'): 3 def logging_decorator(func): 4 @wraps(func) 5 def wrapped_function(*args, **kwargs): 6 log_string = func.__name__ + " was called" 7 print(log_string) 8 # 打开logfile,并写入内容 9 with open(logfile, 'a') as opened_file: 10 # 现在将日志打到指定的logfile 11 opened_file.write(log_string + '\n') 12 return func(*args, **kwargs) 13 return wrapped_function 14 return logging_decorator 15 16 @logit() #myfunc1=logit(myfunc1) 17 def myfunc1(): 18 pass 19 20 myfunc1() 21 # Output: myfunc1 was called 22 # 现在一个叫做 out.log 的文件出现了,里面的内容就是上面的字符串 23 24 @logit(logfile='func2.log') 25 def myfunc2(): 26 pass 27 28 myfunc2() 29 # Output: myfunc2 was called 30 # 现在一个叫做 func2.log 的文件出现了,里面的内容就是上面的字符串