一、什么是装饰器

装饰器是一个很著名的设计模式,经常被用于有切面需求的场景,较为经典的有插入日志、性能测试、事务处理等。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量函数中与函数功能本身无关的雷同代码并继续重用。概括的讲,装饰器的作用就是为已经存在的对象添加额外的功能。简单来讲,可以不严谨地把Python的装饰器看做一个包装函数的函数。

比如,有一个函数:

 def func():
print 'func() run.' if '__main__' == __name__:
func()
运行后将输出:
func() run

现在需要在函数运行前后打印一条日志, 但是又不希望或者没有权限修改函数内部的结构, 就可以用到装饰器:

 def log(function):
def wrapper(*args, **kwargs):
print 'before function [%s()] run.' % function.__name__
rst = function(*args, **kwargs)
print 'after function [%s()] run.' % function.__name__
return rst
return wrapper @log
def func():
print 'func() run.' if '__main__' == __name__:
func()

对于原来的函数"func()"并没有做修改,而是给其使用了装饰器log,运行后的输出为:

 before function [func()] run.
func() run.
after function [func()] run.
把"@log"放到func()函数定义的地方,相当于执行了如下语句:
func = log(func)

因为log()返回了一个函数, 所以原本的func指向了log()返回的函数wrapper。wrapper的参数列表为(*args, **kwargs), 所以其可以接受所有的参数调用, 在wrapper中,先打印了一行

'before function [%s()] run.' % function.__name__,然后执行了原来的函数并记录了返回值,在输出

'after function [%s()] run.' % function.__name__ ,后返回了函数的执行结果。

以下为示例:

 def log(text=''):
def decorator(function):
@functools.wraps(function)
def wrapper(*args, **kwargs):
print 'before function [%s()] run, text: [%s].' % (function.__name__, text)
rst = function(*args, **kwargs)
print 'after function [%s()] run, text: [%s].' % (function.__name__, text)
return rst
return wrapper
return decorator @log('log text')
def func():
print 'func() run.' if '__main__' == __name__:
func()

输出如下:

 before function [func()] run, text: [log text].
func() run.
after function [func()] run, text: [log text].

多层装饰器
多重装饰器的应用:当要求每一个代码块需要两个或多个检查时,这样就需要两个或多个装饰器对此代码块进行监督。

下面给出一个使用装饰器同时对代码进行登录和权限的验证:
 USER_INFO={'is_login':True,'user_type':''}
def check_login(func):
def inner(*args,**kwargs):
if USER_INFO.get('is_login',None):
ret=func(*args,**kwargs)
return ret
else:
print('没登录')
return inner
def check_admin(func):
def inner(*args,**kwargs):
if USER_INFO.get('user_type',None)==2:
ret=func(*args,**kwargs)
return ret
else:
print('权限不足')
return inner @check_login
@check_admin
def index():
print('管理员')
index()

python中的装饰器的更多相关文章

  1. 简单说明Python中的装饰器的用法

    简单说明Python中的装饰器的用法 这篇文章主要简单说明了Python中的装饰器的用法,装饰器在Python的进阶学习中非常重要,示例代码基于Python2.x,需要的朋友可以参考下   装饰器对与 ...

  2. 【Python】python中的装饰器——@

    对装饰器本来就一知半解的,今天终于弄清楚了,Python中的装饰器是对装饰者模式的很好运用,简化到骨子里了. python中为什么需要装饰器,看这里:http://www.cnblogs.com/hu ...

  3. Python 中实现装饰器时使用 @functools.wraps 的理由

    Python 中使用装饰器对在运行期对函数进行一些外部功能的扩展.但是在使用过程中,由于装饰器的加入导致解释器认为函数本身发生了改变,在某些情况下——比如测试时——会导致一些问题.Python 通过  ...

  4. 写python中的装饰器

    python中的装饰器主要用于在已有函数实现功能前附加需要输出的信息,下面将用实例展示我如何写装饰器. 首先分别尝试写装饰器装饰一个无参函数和一个有参函数(被装饰函数仅输出,无返回值情况下) def ...

  5. python中的装饰器decorator

    python中的装饰器 装饰器是为了解决以下描述的问题而产生的方法 我们在已有的函数代码的基础上,想要动态的为这个函数增加功能而又不改变原函数的代码 例如有三个函数: def f1(x): retur ...

  6. python中@property装饰器的使用

    目录 python中@property装饰器的使用 1.引出问题 2.初步改善 3.使用@property 4.解析@property 5.总结 python中@property装饰器的使用 1.引出 ...

  7. 【Python】解析Python中的装饰器

    python中的函数也是对象,函数可以被当作变量传递. 装饰器在python中功能非常强大,装饰器允许对原有函数行为进行扩展,而不用硬编码的方式,它提供了一种面向切面的访问方式. 装饰器 一个普通的装 ...

  8. 三分钟搞定Python中的装饰器

    python的装饰器是python的特色高级功能之一,言简意赅得说,其作用是在不改变其原有函数和类的定义的基础上,给他们增添新的功能. 装饰器存在的意义是什么呢?我们知道,在python中函数可以调用 ...

  9. python cookbook 学习系列(一) python中的装饰器

    简介 装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.它经常用于有切面需求的场景,比如:插入日志.性能测试.事务处理.缓 ...

随机推荐

  1. VC中预处理指令与宏定义详解

    刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能. 一个 ...

  2. (转)PhoneGap工作原理及需改进的地方

    原文:http://mobile.51cto.com/web-330900.htm PhoneGap工作原理及需改进的地方 2012-04-18 16:42 佚名 网络整理 字号:T | T 目前开发 ...

  3. MySQL文件目录格式及存放位置

    了解MYSQL的都知道,在MYSQL中建立任何一张数据表,在其数据目录对应的数据库目录下都有对应表的.frm文件,.frm文件是用来保存每个数据表的元数据(meta)信息,包括表结构的定义等,.frm ...

  4. 防止apache下面直接输入目录访问文件

    有些项目链接会暴露服务器上面的文件地址,如何访问文件被访问呢 方法一: 在项目入口文件下面新加一个.htaccess文件(apache开启重写模式才会加载这个文件,否则这个文件配置不会生效) 文件中加 ...

  5. M3: 将页面元素制作为图片

    本小节将介绍如何将页面元素保存为图片,在前一小节中,我们加入了名称为gridMsg的Grid Control,现在我们将使用RenderTargetBitmap把gridMsg这个页面元素保存为一张图 ...

  6. python数据结构与算法——字典树

    class TrieTree(): def __init__(self): self.root = {} def addNode(self,str): # 树中每个结点(除根节点),包含到该结点的单词 ...

  7. [原创] 用两个stack实现queue的功能

    #include <iostream> #include <stack> using namespace std; class doubleStackToQueue { pri ...

  8. Linux下手动获取当前调用栈

    被问到如何手动获取当前的调用栈,之前碰到过一时没记起来,现在回头整理一下. 其原理是:使用backtrace()从栈中获取当前调用各层函数调用的返回地址,backtrace_symbols()将对应地 ...

  9. Flash Builder如何自定义工作目录

    熟悉了myeclipse可以自定义目录的设置,今天在使用flash builder 时,当导入一个工程到现有项目空间 选择根目录,点击浏览的时候出现的目录是C:\Users\Administrator ...

  10. **stack smashing detecting**

    stack smashing aborted 堆 猛烈撞击 流失 我在使用数据时写了 tmp_row = row + pos[num1][[0]; tmp_col = col + pos[num1][ ...