直接给对象所属的类添加方法;使用组合;(在新类中创建原有类的对象,重复利用已有类的功能)使用继承;(可以使用现有类的,无需重复编写原有类进行功能上的扩展)通常情况下,给一个对象添加新功能有三种方式:
Python 内置装饰器的工作原理一般情况下,优先使用组合,而不是继承。但是装饰器属于第四种,动态的改变对象从而扩展对象的功能。
一般装饰器的应用场景有打印日志,性能测试,事务处理,权限校验;
理解Python装饰器工作原理,首先需要理解闭包这一概念。闭包指的是一个函数嵌套一个函数,内部嵌套的函数调用外部函数的
变量,外部函数返回内嵌函数,这样的结构就是闭包。
装饰器就是闭包的一种应用,但是装饰器参数传递的是函数。
简单的闭包示例:
def add_num(x): def sum_num(y): return x+y return sum_numadd_num5 = add_num(5)total_num = add_num5(100)print(total_num)
注解:
简单计算函数运行时间装饰器示例:
def times_use(func): def count_times(*args, **kwargs): start = time.time() result = func(*args, **kwargs) end = time.time() print(end-start) return result return count_times@times_usedef test_decorator(): time.sleep(2) print("Test Decorator")test_decorator()
注解:
根据日志等级打印日志装饰器示例(带参数的装饰器):
def use_logging(level): def decorator(func): def wrapper(*args, **kwargs): if level == "warn": logging.warn("%s is running"% func.__name__) result = func(*args, **kwargs) print(result) return result return wrapper return decorator@use_logging("warn")def test_decorator(): print("Test Decorator") return "Success"test_decorator()
计算函数运行时间的类装饰器示例:
class logTime: def __init__(self, use_log=False): self._use_log = use_log def __call__(self, func): def _log(*args, **kwargs): start_time = time.time() result = func(*args, **kwargs) print(result) end_time = time.time() if self._use_log: print(end_time-start_time) return result return _log @logTime(True)def test_decorator(): time.sleep(2) print("Test Decorator") return "Success"
functools wraps使用场景使用装饰器虽然能在保存原有代码逻辑的基础上扩展功能,但是原有函数中的元信息会丢失,比如__name__, __doc__,参数列表。针对这种情况
可以使用functools.wraps,wraps也是一个装饰器,但是会将原函数的元信息拷贝到装饰器函数中。
具体使用方法:
from functools import wrapsdef use_logging(level): def decorator(func): @wraps(func) def wrapper(*args, **kwargs): if level == "warn": logging.warn("%s is running"% func.__name__) result = func(*args, **kwargs) print(result) return result return wrapper return decorator@use_logging("warn")def test_decorator(): """" Test Decorator DocString"""" time.sleep(2) print("Test Decorator") return "Success"print(test_decorator.__name__)print(test_decorator.__doc__)
注解:
元信息。关于装饰器的执行顺序
函数定义阶段,执行顺序时从最靠近函数的装饰器开始,从内向外的执行;函数执行阶段,执行顺序时从外而内,一层层的执行;在日常业务中经常会使用多个装饰器,比如权限验证,登录验证,日志记录,性能检测等等使用场景。所以在使用多个装饰器
时,就会涉及到装饰器执行顺序的问题。先说结论,关于装饰器执行顺序,可以分为两个阶段:(被装饰函数)定义阶段、(被装饰函数)执行阶段。
多装饰器示例:
def decorator_a(func): print("Get in Decorator_a") def inner_a(*args, **kwargs): print("Get in Inner_a") result = func(*args, **kwargs) return result return inner_adef decorator_b(func): print("Get in Decorator_b") def inner_b(*args, **kwargs): print("Get in Inner_b") result = func(*args, **kwargs) return result return inner_b@decorator_b @decorator_adef test_decorator(): """test decorator DocString""" print("Test Decorator") return "Success"
运行结果:
Get in Decorator_aGet in Decorator_bGet in Inner_bGet in Inner_aTest Decorator
代码注解:
上述函数使用装饰器可以相当于decorator_b(decorator_a(test_decorator()),即test_dcorator函数作为参数传入到decorator_a函数中,然后打印"Get in Decorator_a",并且返回inner_a函数,给上层decorator_b函数,decorator_b函数接受了作为参数的inner_a函数,打印"Get in Decorator_b",然后返回inner_b函数;此时test_decorator(),即调用了该inner_b函数,inner_b函数打印"Get in inner_b",然后调用inner_a函数,inner_a打印了"Get in Decorator_a",最后调用test_decorator函数。这样从最外层看,就像直接调用了test_decorator函数一样,但是可以在刚刚的过程中实现功能的扩展;参考链接总结https://www.zhihu.com/question/26930016
https://segmentfault.com/a/1190000007837364
https://blog.csdn.net/u013411246/article/details/80571462
以上是内存溢出为你收集整理的粗浅聊聊Python装饰器全部内容,希望文章能够帮你解决粗浅聊聊Python装饰器所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)