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性能分析?

    在分析python代码性能瓶颈,但又不想修改源代码的时候,ipython shell以及第三方库提供了很多扩展工具,可以不用在代码里面加上统计性能的装饰器,也能很方便直观的分析代码性能.下面以我自己实 ...

  3. python decorator的理解

    一.decorator的作用 装饰器本质上是一个Python函数,可以让其他函数在不做任何代码变动的前提下增加额外功能. 装饰器的返回值也是一个函数对象.python里函数也是对象. 它经常用于有切面 ...

  4. python decorator simple example

    Why we need the decorator in python ? Let's see a example: #!/usr/bin/python def fun_1(x): return x* ...

  5. Python性能分析指南

    http://www.admin10000.com/document/2861.html 尽管并非每个你写的Python程序都需要严格的性能分析,但了解一下Python的生态系统中很多优秀的在你需要做 ...

  6. Python代码分析工具之dis模块

    转自:http://hi.baidu.com/tinyweb/item/923d012e8146d00872863ec0  ,格式调整过. 代码分析不是一个新的话题,代码分析重要性的判断比较主观,不同 ...

  7. 基于binlog来分析mysql的行记录修改情况(python脚本分析)

          最近写完mysql flashback,突然发现还有有这种使用场景:有些情况下,可能会统计在某个时间段内,MySQL修改了多少数据量?发生了多少事务?主要是哪些表格发生变动?变动的数量是怎 ...

  8. Python丨Python 性能分析大全

    虽然运行速度慢是 Python 与生俱来的特点,大多数时候我们用 Python 就意味着放弃对性能的追求.但是,就算是用纯 Python 完成同一个任务,老手写出来的代码可能会比菜鸟写的代码块几倍,甚 ...

  9. python decorator 基础

    一般来说,装饰器是一个函数,接受一个函数(或者类)作为参数,返回值也是也是一个函数(或者类).首先来看一个简单的例子: # -*- coding: utf-8 -*- def log_cost_tim ...

随机推荐

  1. spring mvc 4 校验

    一.controller中添加: @ResourceGatewayValidator gatewayValidator; @RequestMapping(value = "/gateway/ ...

  2. 判断AngularJS渲染页面完成

    $scope.$on('$viewContentLoaded', function(){ }); // 或者 $scope.$watch('$viewContentLoaded', function( ...

  3. fir.im Weekly - 如何打造真正的工程师文化

    好的工程师,无法忍受低效且无趣的工作.优秀的技术团队应该自上而下的地推进技术平台化建设.DevOps.自动化构建.测试和部署流程,积极采用合适的第三方工具或创造工具,进行周期性的前沿技术分享等等. 先 ...

  4. MVC中使用RazorPDF创建PDF

    这篇文章主要介绍使用Nuget package中的RazorPDF简单的创建PDF的方法. 关于RazorPDF 这个Nuget Package由Al Nyveldt创建.它内部使用ITextShar ...

  5. BarManager.ContextMenu

    <!--Search & List Area--> <dxb:BarManager Name="barManager1" dxlc:DockLayoutC ...

  6. C# 延迟处理类 Lazy

    using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Lazy ...

  7. js分页

    今天看了下妙味课堂的教程,写了下关于分页的js代码,写完的感觉就是有点小麻烦,需要很多if判断,思路要清晰 点击预览:http://peng666.github.io/blogs/page <! ...

  8. 用终端直接在桌面生成text文件

    简单的两行命令: cd Desktop/  按回车 touch 888.text 按回车就会在桌面生成名称为888的text文件 用途:做demo的时候可以加一个说明文档进去,这样下次可以很方便的查看

  9. cron服务 ubuntu

    linux 定时执行crontab  crontab -e 进入一个vi 编辑界面 在最后一行加上 */30 * * * * netstat > /tmp/net.log 表示每隔30分就执行n ...

  10. linux命令后面常见的&gt;/dev/null 和 2&gt;&amp;1 的含义

    >/dev/null 输出到空设备,表示丢掉输出信息. 2 > &1 将输出到标准错误的信息输出到标准输出设备(通常是屏幕) 有3个默认的i/o, 0 是标准输入,一般是键盘 1 ...