zoukankan      html  css  js  c++  java
  • python中的装饰器

    一、什么是装饰器

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

    比如,有一个函数:

    1 def func():
    2     print 'func() run.'
    3 
    4 if '__main__' == __name__:
    5     func()
    6 运行后将输出:
    7 func() run

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

     1 def log(function):
     2     def wrapper(*args, **kwargs):
     3         print 'before function [%s()] run.' % function.__name__
     4         rst = function(*args, **kwargs)
     5         print 'after function [%s()] run.' % function.__name__
     6         return rst
     7     return wrapper 
     8 
     9 @log
    10 def func():
    11     print 'func() run.'
    12 
    13 if '__main__' == __name__:
    14     func()

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

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

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

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

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

    以下为示例:

     1 def log(text=''):
     2     def decorator(function):
     3         @functools.wraps(function)
     4         def wrapper(*args, **kwargs):
     5             print 'before function [%s()] run, text: [%s].' % (function.__name__, text)
     6             rst = function(*args, **kwargs)
     7             print 'after function [%s()] run, text: [%s].' % (function.__name__, text)
     8             return rst 
     9         return wrapper
    10     return decorator
    11 
    12 @log('log text')
    13 def func():
    14     print 'func() run.'
    15 
    16 if '__main__' == __name__:
    17     func()
    View Code

    输出如下:

    1 before function [func()] run, text: [log text].
    2 func() run.
    3 after function [func()] run, text: [log text].
    多层装饰器
    多重装饰器的应用:当要求每一个代码块需要两个或多个检查时,这样就需要两个或多个装饰器对此代码块进行监督。
    下面给出一个使用装饰器同时对代码进行登录和权限的验证:
     1 USER_INFO={'is_login':True,'user_type':'2'}
     2 def check_login(func):
     3     def inner(*args,**kwargs):
     4         if USER_INFO.get('is_login',None):
     5             ret=func(*args,**kwargs)
     6             return ret
     7         else:
     8             print('没登录')
     9     return inner
    10 def check_admin(func):
    11     def inner(*args,**kwargs):
    12         if USER_INFO.get('user_type',None)==2:
    13             ret=func(*args,**kwargs)
    14             return  ret
    15         else:
    16             print('权限不足')
    17     return inner
    18 
    19 @check_login
    20 @check_admin
    21 def index():
    22     print('管理员')
    23 index()
  • 相关阅读:
    python 如何将md5转为16字节
    linux非root用户执行开机启动程序
    python 正则表达式的使用
    Go随机数的使用
    Go 的类型断言type assertion
    go get中的...
    Go语言圣经
    python入门第三十五天--事件驱动模型(补)练习理解
    MySQL_Ubuntu安装
    JAVA入门基础--数据类型
  • 原文地址:https://www.cnblogs.com/panwenbin-logs/p/5558416.html
Copyright © 2011-2022 走看看