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》

原文地址:https://www.cnblogs.com/marton/p/10872601.html