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. 冲刺一 (Day 2)

    冲刺一 (Day 2) 小组讨论结果 经过今天的小组会议,小组各成员决定先进一步探讨项目的需求.因为我们明白要砍倒一棵树,磨刀才是前期的重中重之重,实际中也有不少以为前期需求没做好而,在项目后期推翻重 ...

  2. PAT 02-线性结构1 两个有序链表序列的合并 (15分)

    本题要求实现一个函数,将两个链表表示的递增整数序列合并为一个递增的整数序列. 函数接口定义: List Merge( List L1, List L2 ); 其中List结构定义如下: typedef ...

  3. C语言编程技巧-signal(信号)[转]

    自 http://www.uml.org.cn/c++/200812083.asp 信号是Linux编程中非常重要的部分,本文将详细介绍信号机制的基本概念.Linux对信号机制的大致实现方法.如何使用 ...

  4. TCP应用编程

    TCP是Transmission Control Protocol(传输控制协议)的简称,是TCP/IP体系中面向连接的运输层协议,在网络中提供全双工的和可靠的服务. TCP协议最主要的特点是: 1) ...

  5. [HTML]JS全屏代码

    video全屏参考:https://www.thecssninja.com/javascript/fullscreen <!doctype html> <html> <h ...

  6. socket-自我总结(2)

    这里总结下一个服务端与多个客户端之间的通信. 先看demo: #/usr/bin/env python #_*_coding:utf-8_*_ __author__ = 'ganzl' import ...

  7. C# 导入EXCEL 报错外部表不是预期的格式错误 .

    错误经过:在读取Excel时,出现外部表不是预期的格式 错误原因1: 由于Excel 97-2003的连接格式与Excel 2010 的 不同造成. 以下是从网上摘抄原文 Excel “Externa ...

  8. tomcat运行时候出现java.net.BindException: Address already in use: JVM_Bind错误解决方法

    问题原因:我们在运行tomcat时候一般用8080端口,但是当端口被占用的时候便不能正常使用tomcat并且会造成上述的错误.而端口被占用的原因有很多,这次的原因是因为装好tomcat以后已经启动了一 ...

  9. mongodb遇到的错误

    1. [root@localhost bin]# ./mongod -dbpath /data/db --logpath /usr/local/mongodb/log --13T18:: F CONT ...

  10. ueditor使用canvas在图片上传前进行压缩

    之前就看到H5使用canvas就可以在前端使用JS压缩图片,这次接到任务要把这个功能嵌入到ueditor里面去,以节省流量,减轻服务器压力. H5使用canvas进行压缩的代码有很多,核心原理就是创建 ...