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

Python Decorator分析的更多相关文章

  1. Python Decorator 和函数式编程

    看到一篇翻译不错的文章,原文链接: Python Decorator 和函数式编程

  2. Python股票分析系列——自动获取标普500股票列表.p5

    该系列视频已经搬运至bilibili: 点击查看 欢迎来到Python for Finance教程系列的第5部分.在本教程和接下来的几节中,我们将着手研究如何为更多公司提供大量的定价信息,以及如何一次 ...

  3. Python股票分析系列——基础股票数据操作(二).p4

    该系列视频已经搬运至bilibili: 点击查看 欢迎来到Python for Finance教程系列的第4部分.在本教程中,我们将基于Adj Close列创建烛台/ OHLC图,这将允许我介绍重新采 ...

  4. Python股票分析系列——基础股票数据操作(一).p3

    该系列视频已经搬运至bilibili: 点击查看 欢迎来到Python for Finance教程系列的第3部分.在本教程中,我们将使用我们的股票数据进一步分解一些基本的数据操作和可视化.我们将要使用 ...

  5. Python股票分析系列——数据整理和绘制.p2

    该系列视频已经搬运至bilibili: 点击查看 欢迎来到Python for Finance教程系列的第2部分. 在本教程中,我们将利用我们的股票数据进一步分解一些基本的数据操作和可视化. 我们将要 ...

  6. Python股票分析系列——系列介绍和获取股票数据.p1

    本系列转载自youtuber sentdex博主的教程视频内容 https://www.youtube.com/watch?v=19yyasfGLhk&index=4&list=PLQ ...

  7. Python数据采集分析告诉你为何上海二手房你都买不起

    感谢关注Python爱好者社区公众号,在这里,我们会每天向您推送Python相关的文章实战干货. 来吧,一起Python. 对商业智能BI.大数据分析挖掘.机器学习,python,R等数据领域感兴趣的 ...

  8. 【转】python模块分析之collections(六)

    [转]python模块分析之collections(六) collections是Python内建的一个集合模块,提供了许多有用的集合类. 系列文章 python模块分析之random(一) pyth ...

  9. 【转】python模块分析之unittest测试(五)

    [转]python模块分析之unittest测试(五) 系列文章 python模块分析之random(一) python模块分析之hashlib加密(二) python模块分析之typing(三) p ...

随机推荐

  1. scrum.4

    1.准备看板. 形式参考图4. 2.任务认领,并把认领人标注在看板上的任务标签上. 先由个人主动领任务,PM根据具体情况进行任务的平衡. 然后每个人都着手实现自己的任务. 3.为了团队合作愉快进展顺利 ...

  2. js浏览器对象的属性和方法

    1.window对象 /*1.计算浏览器窗口大小*/ //不算滚动条: var width = window.innerWidth; var height = window.innerHeight; ...

  3. C#中获得机器的字符编码webName信息

    在一次解决编码的问题过程中,发现Encoding.GetEncoding("GB2312") == Encoding.GetEncoding("GBK"),到底 ...

  4. RequireJS基础(二)

    上一篇是把整个jQuery库作为一个模块.这篇来写一个自己的模块:选择器. 为演示方便这里仅实现常用的三种选择器id,className,attribute. RequireJS使用define来定义 ...

  5. 实例学习SQL的Select命令

    1.查找员工的编号.姓名.部门和出生日期,如果出生日期为空值,--显示日期不详,并按部门排序输出,日期格式为yyyy-mm-dd.select emp_no ,emp_name ,dept ,isnu ...

  6. 《深度探索C++对象模型(Inside The C++ Object Model )》学习笔记

    转载:http://dsqiu.iteye.com/blog/1669614 第一章 关于对象 使用class封装之后的布局成本: class并没有增加成本,data members直接内含在每一个c ...

  7. AJAX避免服务器调用上个页面缓存的办法

    GET 请求 一个简单的 GET 请求: xmlhttp.open("GET","demo_get.asp",true); xmlhttp.send(); 亲自 ...

  8. Net 分页功能的实现

    首先写一个接口   1 2 3 4 5 6 public interface IPagedList     {         int CurrentPageIndex { get; set; }   ...

  9. DOM元素querySelectorAll可能让你意外的特性表现

    一.时间紧急,废话少说 本文所在的页面藏匿了下面这些代码: <img id="outside"> <div id="my-id"> &l ...

  10. tomcat启动时 myeclipse控制台中文乱码

    情况1: tomcat中conf目录下有个叫server.xml的文件,里面 <Connector port="8080" protocol="HTTP/1.1&q ...