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

    装饰器

    简述

    如果我们想给一个类扩充功能,我们可以通过继承和组合,但是如果我们如果想给一个方法添加额外的功能呢?

    装饰器可以满足这个需求。

    装饰器是一个可调用的对象,其参数是一个函数,这个函数通常称为被装饰的函数。

    装饰器可能会处理被装饰的函数,然后返回一个函数或一个可调用对象。

    来个栗子,有一个名为decorate的装饰器

    def decorate(func):
        def inner():
            print("inner")
        return inner
    
    @decorate
    def target():
        print("target")
    
    target() #inner

    上述的代码等价于下述的代码

    def decorate(func):
        def inner():
            print("inner")
        return inner
    
    def target():
        print("target")
    
    target = decorate(target)
    target() #inner

    装饰器特性

    (1)能把被装饰的函数替换了其他的函数

    这个特性从上面的栗子就可以看出

    (2)装饰器在加载模块时立即执行

    被装饰的函数只有在调用时才执行

    def decorate(func):
        print('decorate functon:', func.__name__)
        def inner():
            print('inner')
    
        return inner
    
    @decorate
    def func1():
        print('func1')
    
    if __name__ == '__main__':
        func1()

    导入时,如果我在另一个模块导入上述代码所在的模块,结果如下:

    import decorate
    #decorate functon: func1

    运行时,如果我直接运行这个模块,结果如下:

    #decorate functon: func1
    #inner

    一般而言,装饰器通常在一个模块中定义,然后应用到其他模块中的函数上,大多数装饰器会在内部定义一个函数然后将其返回。

    装饰器的典型行为

    把被装饰的函数替换成新的函数,两者接受相同的参数,返回被装饰的函数本该返回的值,

    同时,还会做些额外操作。

    实际应用

    计时统计、记录日志,缓存运算结果等

    案例1

    编写一个记录函数运行时间的装饰器

    import time
    def log_time(func):
        def run_time(*args, **kwargs):
            begin_time = time.time()
            res = func(*args, **kwargs)
            print('spent {}s'.format(time.time() - begin_time))
         return res
    return run_time @log_time def sleep_func(): time.sleep(1) sleep_func()

    案例2

    使用类编写一个装饰器

    import time
    
    class LogTime:
    
        def __call__(self, func):
            def run_time(*args, **kwargs):
                begin_time = time.time()
                res = func(*args, **kwargs)
                print('spent {}s'.format(time.time() - begin_time))
                return res
            return run_time
    
    @LogTime()
    def sleep_func():
        time.sleep(1)
    
    sleep_func()

    案例3

    给装饰器传递参数

    class LogTime:
    
        def __init__(self, use_int):
            self.use_int = use_int
    
        def __call__(self, func):
            def run_time(*args, **kwargs):
                begin_time = time.time()
                res = func(*args, **kwargs)
                if self.use_int:
                    print('spent {}s'.format(int(time.time() - begin_time)))
                else:
                    print('spent {}s'.format(time.time() - begin_time))
                return res
            return run_time
    
    @LogTime(use_int=True)
    def sleep_func():
        time.sleep(1)
    
    sleep_func

    参考资料:《流畅的python》

  • 相关阅读:
    【郑轻邀请赛 G】密室逃脱
    【郑轻邀请赛 C】DOBRI
    【郑轻邀请赛 F】 Tmk吃汤饭
    【郑轻邀请赛 I】这里是天堂!
    【郑轻邀请赛 B】base64解密
    【郑轻邀请赛 A】tmk射气球
    【郑轻邀请赛 H】 维克兹的进制转换
    解决adb command not found以及sdk环境配置
    adb shell 命令详解,android, adb logcat
    Unexpected exception 'Cannot run program ... error=2, No such file or directory' ... adb'
  • 原文地址:https://www.cnblogs.com/marton/p/10872601.html
Copyright © 2011-2022 走看看