decorator本身是一个函数,这个函数的功能是接受被修饰的函数(decorated)作为参数,返回包装函数(wrapper)替换被修饰函数(decorated)。

@decorator
func

等同于 func = decorator(func)。大部分情况下wrapper函数必须要和decorated函数具有相同的参数,这样在wrapper函数中可以执行decorated函数,并增加一些拓展流程。基于此decorator的原则如下:

  • 对于自定义decorator,wrapper函数的参数要参考目标函数设计。
  • 如果使用系统decorator,因为wrapper函数是明确的,所以目标函数的设计要参考wrapper函数的参数。

decorator接受目标函数为参数,并返回wrapper函数,因此不能接受额外的参数。为了传送额外的参数给decorator函数,可以创建decorator maker函数接受参数并返回decorator函数,然后使用decorator完成函数替换,将目标函数替换为wrapper函数。

示例:

def mydecorator_maker(*args, **kwargs):
print 'this is decorator maker function... with args %s, kwargs %s' % (args, kwargs)
def mydecorator(func):
print 'this is decorator... with args %s, kwargs %s' % (args, kwargs)
def decorator_wrapper(func_arg1, func_arg2):
print 'this is decorator wrapper, before function... with arg1 %s, arg2 %s' % (func_arg1, func_arg2)
func(func_arg1, func_arg2)
print "this is decorator wrapper, after function"
return decorator_wrapper
return mydecorator @mydecorator_maker(1, 2, 3, test='test')
def mydecorated_function(func_arg1, func_arg2):
print 'this is decorated function with arg1 %s, arg2 %s' % (func_arg1, func_arg2) mydecorated_function('lily', 'Baby')

output:

this is decorator maker function... with args (1, 2, 3), kwargs {'test': 'test'}

this is decorator... with args (1, 2, 3), kwargs {'test': 'test'}

this is decorator wrapper, before function... with arg1 lily, arg2 Baby

this is decorated function with arg1 lily, arg2 Baby

this is decorator wrapper, after function

this is decorator maker function...

这种通过一个maker函数来接受额外的参数,并且做一些额外参数的处理的实现方式非常简明。拓展一下,因为decorator的函数替换的特点,可以对decorator函数进行一次decorator来实现额外参数的处理。首先梳理一下实现逻辑:

  • decorator的原理是将被decorated函数替换为wrapper函数。wrapper函数获取decorated函数的参数,执行decorated函数并在之前之后进行业务拓展处理。
  • decorated decorator函数根据上述原理,和普通的decorator没有不同。只是在decorator上加一个decorator使其增加处理额外参数的能力。
  • decoratordecorator将原decorator函数变为一个接受参数的wrapper函数,在这个函数执行后将decorator返回。继续之前的decorator流程。
  • decoratordecorator函数中的wrapper函数与普通的wrapper函数最大的不同在于不执行decorator函数,而是返回decorator函数。因此不需要保持参数的一直,带来额外参数的支持。

    这种参数的变换不一致和上述wrapper参数保持一致的原则有悖,但是依然符合decorator进行函数替换的基本功能设计。

示例:

def decorator_decorator(decorator_to_decorated):
print 'This decorator decorator will decorate decorator passed in...'
print 'passed in decorator is %s ' % decorator_to_decorated
def decorator_wrapper(*args, **kwargs):
print 'decorator wrapper do something with args %s, kwargs %s...' % (args, kwargs)
return decorator_to_decorated
return decorator_wrapper @decorator_decorator
def decorated_decorator(func):
print 'func %s is decorated here' % func
def wrapper(func_arg1, func_arg2):
print 'wrapper with arg1 %s, args2 %s' % (func_arg1, func_arg2)
return func(func_arg1, func_arg2)
return wrapper @decorated_decorator(1, 2, 3, test='test')
def decorated_function(func_arg1, func_arg2):
print 'decorated function with func arg1 %s, arg2 %s' % (func_arg1, func_arg2)
print 'do something in decorated function' decorated_function('Liliy', 'Baby')

output:

This decorator decorator will decorate decorator passed in...

passed in decorator is <function decorateddecorator at 0x111a99c80>

decorator wrapper do something with args (1, 2, 3), kwargs {'test': 'test'}...

func <function decoratedfunction at 0x111b2bc08> is decorated here

wrapper with arg1 Liliy, args2 Baby

decorated function with func arg1 Liliy, arg2 Baby

do something in decorated function

最新文章

  1. Cocos2d-x 3.2 学习笔记(十六)保卫萝卜 游戏主循环与定时器
  2. 安装oracle 12c RAC遇到的一些问题
  3. C++ 面向对象的三个特点--多态性(二)
  4. HDU 1150 Machine Schedule (二分图最小点覆盖)
  5. 文件上传利器SWFUpload使用指南
  6. 更加详细的Log4net的配置
  7. 使用ARM和VMSS创建自动扩展的web集群
  8. OCA读书笔记(4) - 管理数据库实例
  9. Python之sqlite3
  10. 十九、Hadoop学记笔记————Hbase和MapReduce
  11. jsp篇 之 jsp页面中的路径问题
  12. 框架的一些bug问题记录
  13. MFC编程之数值调节按钮
  14. 在Struts.xml中的result元素指的是:指定动作类的动作方法执行完后的结果视图.
  15. ubuntu-docker入门到放弃(七)操作系统
  16. Vue-嵌套路由
  17. ossec变更alert等级及配置邮件预警
  18. 只输FLOAT值 TEXTBOX
  19. window自带字体
  20. 2015 UESTC 搜索专题F题 Eight Puzzle 爆搜

热门文章

  1. MySQL 第七天(核心优化一)
  2. DEM数据如何生成高程点
  3. asp.net core获取自定义json的配置内容
  4. viewgroup用addview添加的view不显示问题
  5. HP_UX HBA 卡信息收集脚本
  6. 经典的Hello World VFP前端调后端C# Webservice
  7. QPainter类的一些问题
  8. 只有一个radio的单选框如何在选中后取消选中
  9. iOS 判断字符串是否为空
  10. 单位换算(格式化十进制数-B),获取时间工具类CommenUtil