Python 装饰器基础用法 基本格式

x33g5p2x  于2021-09-19 转载在 Python  
字(1.6k)|赞(0)|评价(0)|浏览(228)

装饰器:
用一个函数去装饰另一个函数或类,为其提供额外的能力
实现了一种名为代理模式的经典设计模式

​ 横切关注功能(cross-concern):跟正常的业务没有必然联系的功能
​ 这样的功能最适合用装饰器(代理模式)来实现

举个例子:现有模仿下载与上传并记录这个过程耗时功能的函数:

下载:

def download(filename):
    start_time = time.time()
    print(f'开始下载{filename}')
    time.sleep(random.randrange(3, 7))
    print(f'{filename}下载完成')
    end_time = time.time()
    print(f'下载耗时:{(end_time - start_time):.4f}')

上传:

def upload(filename):
    start_time = time.time()
    print(f'开始上传{filename}')
    time.sleep(random.randrange(5,9))
    print(f'{filename}上传完成')
    end_time = time.time()
    print(f'下载耗时:{(end_time - start_time):.4f}')

上述代码显而易见的问题就是代码重复,这是相当糟糕的。这种函数内的重复代码就可以用装饰器来解决。而且当我们不需要记录执行时间时可随时取消。

装饰器基本语法

def log_time(func):  # 参数是被装饰的函数
    @wraps(func)   # 装饰器建议都添加,可随时取消装饰器
    def wrapper(*args,**kwargs):  #针对原函数带参
        # 新功能
        
        result = func(*args,**kwargs)   # 调用原函数
        # 新功能
        
        return result   #返回原函数的返回值
    return wrapper   # 返回带有装饰功能的函数

装饰器函数的参数是被装饰的函数,它返回的是带有装饰功能的函数

只需要在上述格式空白处添加新功能即可。

示例

本例记录时间功能可编写为:

def log_time(func):  # 参数是被装饰的函数

    @wraps(func)   # 装饰器建议都添加,可随时取消装饰器
    def wrapper(*args,**kwargs):
        # 新功能
        start_time = time.time()
        result = func(*args,**kwargs)   # 调用原函数
        # 新功能
        end_time = time.time()
        print(f'{func.__name__}执行耗时:{end_time-start_time:.4f}')
        return result   #返回原函数的返回值
    return wrapper   # 返回带有装饰功能的函数

装饰器的使用方法

写好装饰器有两种使用方法:

def download(filename):
    print(f'开始下载{filename}')
    time.sleep(random.randrange(3,7))
    print(f'{filename}下载完成')
    
if __name__ == '__main__':
    # 装饰器用法一:
    download = log_time(download)
    download('Python入门.pdf')
    
 #输出: 
 #开始下载Python入门.pdf
 #Python入门.pdf下载完成
 #download执行耗时:4.0001
# 装饰器用法二
@log_time
def upload(filename):
    print(f'开始上传{filename}')
    time.sleep(random.randrange(5,9))
    print(f'{filename}上传完成')
    
#输出:
#开始上传Python人工智能.pdf
#Python人工智能.pdf上传完成
#upload执行耗时:5.0006

上面提到的@wraps具体功能就是取消装饰器的作用,这里就是取消耗时记录:

download.__wrapped__('数据分析.pdf')

#输出:
#开始下载数据分析.pdf
#数据分析.pdf下载完成

相关文章