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

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

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

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

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

下载:

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

上传:

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

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

装饰器基本语法

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

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

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

示例

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

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

装饰器的使用方法

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

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

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

  1. download.__wrapped__('数据分析.pdf')
  2. #输出:
  3. #开始下载数据分析.pdf
  4. #数据分析.pdf下载完成

相关文章