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. mysql 数据库可以非本地访问

      GRANT ALL PRIVILEGES ON 数据库名.* TO root@'%' IDENTIFIED BY '密码' WITH GRANT OPTION;

  2. input框中的name和id的区别

    1. 可以说几乎每个做过Web开发的人都问过,到底元素的ID和Name有什么区别阿?为什么有了ID还要有Name呢?! 而同样我们也可以得到最classical的答案:ID就像是一个人的身份证号码,而 ...

  3. spring开发的总结

    1,当出现无法创建bean,( Error creating bean with name 'fileUploadService': Injection of resource dependencie ...

  4. LFS初次成功+如何粘贴复制LFS命令

    搞了几次LFS,终于成功了,总算舒了一口气. 这次搞LFS用到的资料:LFS文档:http://www.ha97.com/book/lfs-book-6.6/index.html  一份简单的指导文章 ...

  5. Yii源码阅读笔记(二十五)

    Module类中剩余部分代码,通过控制器ID实例化当前模块的控制器,当前模块的Action方法的前置和后置方法: /** * This method is invoked right before a ...

  6. HDU 1085 Holding Bin-Laden Captive --生成函数第一题

    生成函数题. 题意:有币值1,2,5的硬币若干,问你最小的不能组成的币值为多少. 解法:写出生成函数: 然后求每项的系数即可. 因为三种硬币最多1000枚,1*1000+2*1000+5*1000=8 ...

  7. mysql单表查询&amp;&amp;多表查询(职员表14+9)

    dept(deptno,dname,loc) emp(empno,ename,job,mgr,hiredate,sal,COMM,deptno) salgrade(grade,losal,hisal) ...

  8. C#中调用Windows API的要点 .

    介绍 API(Application Programming Interface),我想大家不会陌生,它是我们Windows编程的常客,虽然基于.Net平台的C#有了强大的类库,但是,我们还是不能否认 ...

  9. WebStorm配置(2016/11/18更新)

    目录: 1.主题设置 2.模板设置 3.代码段设置 4.快捷键设置 5.显示行号+自动换行 6.配置github 7.常用快捷键 8.软件下载(破解版及汉化包) 1.主题设置 1)ctrl+alt+s ...

  10. ORA-01790 错误处理

    今天在练手的时候出现了一个ORA-01790 的错误,决定把他写下来保留起来. 先来创建两张测试用的简单的表. SQL> create table test01 (id number(3),na ...