简介

装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能,我们也称之为AOP(面向切面编程)

原理

实现装饰器的最主要的原因是python中一切皆为对象,我们会把方法看做一个对象包装起来

实现

首相,我们先来看一个简单的例子,有一个add方法:

def add(x, y):
print('result is {}'.format(x + y))

现在有一个新的需求,我们想在这个方法执行完之后print一句话证明他执行成功了,同样我们又不想修改这个add方法,那我们可以新建一个方法:

def printres(func):
func()
print('Done')
printres(add)

那这样是ok的。但是这样的话,我们每次都要将一个函数作为参数传递给printres函数。而且这种方式已经破坏了原有的代码逻辑结构,之前执行业务逻辑时,执行运行add(),但是现在不得不改成printres(add)。那么有没有更好的方式的呢?当然有,答案就是装饰器。我就直接贴代码:

# coding=utf-8
"""
学习装饰器 2016-08-20 by oldman
"""
from functools import wraps """
先来看一个简单的装饰器
""" def decor1(func):
@wraps(func)
def wrapper(*args, **kwargs):
func(*args, **kwargs)
print('i am a decorate') return wrapper @decor1
def add(x, y):
print('result is {}'.format(x + y)) # if __name__ =="__main__":
# add(2,3) """
再来看一个带参数的装饰器
""" def decor2(parm):
"""
parm为装饰器用到的参数
""" def _decor2(func): # func为被装饰的函数
@wraps(func) # wraps 装饰器会把func的元数据带过来
def wrapper(*args, **kwargs):
if parm:
func(*args, **kwargs)
print('I am true')
else:
print('sorry, false') return wrapper return _decor2 @decor2(True) # 这里装饰器的参数为True
def add1(x, y):
print('result is {}'.format(x + y)) if __name__ == '__main__':
add1(2, 3)

注意到functools.wraps,wraps本身也是一个装饰器,它能把原函数的元信息拷贝到装饰器函数中,这使得装饰器函数也有和原函数一样的元信息了,如果不在装饰器里使用@wrap的话,被装饰的函数的元信息会丢失。

总结

这是一个很好的解决方案,不得不感叹python的灵活,人生苦短,我用python。

源代码地址(Github)

参考文章:http://www.zhihu.com/question/26930016

学习交流群 :226704167

python cookbook 学习系列(一) python中的装饰器的更多相关文章

  1. python开发学习-day04(迭代器、生成器、装饰器、二分查找、正则)

    s12-20160123-day04 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...

  2. python框架之Django(8)-CBV中添加装饰器

    现有如下检查登录装饰器: from functools import wraps def check_login(func): @wraps(func) def inner(request, *arg ...

  3. 《Python爬虫学习系列教程》学习笔记

    http://cuiqingcai.com/1052.html 大家好哈,我呢最近在学习Python爬虫,感觉非常有意思,真的让生活可以方便很多.学习过程中我把一些学习的笔记总结下来,还记录了一些自己 ...

  4. [转]《Python爬虫学习系列教程》

    <Python爬虫学习系列教程>学习笔记 http://cuiqingcai.com/1052.html 大家好哈,我呢最近在学习Python爬虫,感觉非常有意思,真的让生活可以方便很多. ...

  5. Comprehensive learning path – Data Science in Python深入学习路径-使用python数据中学习

    http://blog.csdn.net/pipisorry/article/details/44245575 关于怎么学习python,并将python用于数据科学.数据分析.机器学习中的一篇非常好 ...

  6. python cookbook学习1

    python cookbook学习笔记 第一章 文本(1) 1.1每次处理一个字符(即每次处理一个字符的方式处理字符串) print list('theString') #方法一,转列表 结果:['t ...

  7. PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的按钮改变缺省文字的方法

    在Qt Designer中可以预先定义标准按钮,相关支持的标准按钮请见<PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的StandardButton ...

  8. PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox增加自定义按钮的方法

    在Qt Designer中可以预先定义标准按钮,相关支持的标准按钮请见<PyQt(Python+Qt)学习随笔:Designer中的QDialogButtonBox的StandardButton ...

  9. PyQt(Python+Qt)学习随笔:Designer中QDialogButtonBox确认clicked信号是哪个按钮发送的方法

    一.引言 QDialogButtonBox本身只提供4种信号,分别是accepted.rejected.clicked和helpRequested,在<PyQt(Python+Qt)学习随笔:D ...

随机推荐

  1. C#开发微信门户及应用(9)-微信门户菜单管理及提交到微信服务器

    微信公众号(包括服务号和订阅号)都可以对菜单进行自定义设置,我们为了方便管理,一般先把菜单数据在本地管理维护,需要更新的时候,把它们更新到微信服务器上就可以了.本文基于这个方式,介绍我的微信门户平台管 ...

  2. VS资源编辑器常见错误RC1000到RC1208

    资源编译器错误RC1000到RC1208 以下主题包括资源编译器错误RC1000至RC1208: 资源编译器致命错误RC1000未知致命错误记下错误的情况下,尝试找出问题,并创建一个重现的测试案例,然 ...

  3. 企业级应用架构模式N-Tier多层架构

              先来看经典的3层架构,看下图: 涉及到平台可以是: Ruby on Rails, Java EE, ASP.NET, PHP, ColdFusion, Perl, Python 层 ...

  4. GJM : Unity3D HIAR -【 快速入门 】 五、导出 Android 工程、应用

    导出 Android 工程.应用 在开始之前,请务必先保存您的工程,同时确认您已经安装 Android SDK 和 JDK.安装操作请参考以下链接: 搭建开发环境 Step 1. 设置 Android ...

  5. JQuery操作类数组的工具方法

    JQuery学习之操作类数组的工具方法 在很多时候,JQuery的$()函数都返回一个类似数据的JQuery对象,例如$('div')将返回div里面的所有div元素包装的JQuery对象.在这中情况 ...

  6. SVG图形引用、裁切、蒙版

    SVG图形引用.裁切.蒙版,使用三个标签: 1. <use>标签创建图形引用 2. <clipPath>标签裁切图形 3. <mask>标签创建蒙版  ...

  7. 谨慎使用Sql server data tool 架构比对排除

      现象:某个架构始终不能更新     VS中使用SSDT很方便,进行架构比对时,可以选择性的更新.但在排除操作上,要相当谨慎.往往排除的并不是一个差异项. 如下图,表或视图的差异,如果有多处,可以选 ...

  8. 解析Jquery取得iframe中元素的几种方法

    iframe在复合文档中经常用到,利用jquery操作iframe可以大幅提高效率,这里收集一些基本操作,需要的朋友可以参考下   DOM方法:父窗口操作IFRAME:window.frames[&q ...

  9. 理解OVER子句

    简介 Over子句在SQLServer 2005中回归,并且在2012中得到了扩展.这个功能主要结合窗口函数来使用:也可以在序列函数"NEXT VALUE FOR"使用.OVER子 ...

  10. Spark SQL 之 Data Sources

    #Spark SQL 之 Data Sources 转载请注明出处:http://www.cnblogs.com/BYRans/ 数据源(Data Source) Spark SQL的DataFram ...