zoukankan      html  css  js  c++  java
  • python cookbook 学习系列(一) python中的装饰器

    简介

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

    原理

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

    实现

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

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

    现在有一个新的需求,我们想在这个方法执行完之后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)
    View Code

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

    总结

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



    源代码地址(Github)

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

    学习交流群 :226704167

  • 相关阅读:
    【iOS】The identity used sign the executable is no longer valid.
    【iOS】iOS Error Domain=NSCocoaErrorDomain Code=3840 "未能完成操作。(“Cocoa”错误 3840。)"
    Exponentiation
    A+B Problem
    括号配对
    单调递增最长子序列
    Fibonacci数
    ASCII码排序
    基础练习 数的读法
    基础练习 Sine之舞
  • 原文地址:https://www.cnblogs.com/lip0121/p/5792176.html
Copyright © 2011-2022 走看看