python学习笔记3.4-函数装饰器
发布日期:2021-05-15 15:40:51 浏览次数:19 分类:精选文章

本文共 2402 字,大约阅读时间需要 8 分钟。

软件开发过程中,重复性工作是 Avoid 的关键技能。在 Python 中,当需要创建高度重复的代码时,元 Programing 是最常采用的解决方案。简单而言,元编程的核心目标就是通过创建函数和类来操纵代码,实现行为的生成、修改和包装。Python 提供了多种元编程技巧,如装饰器、类装饰器、元类,以及用途广泛的主题工具(如对象签名、exec()用于执行代码以及检查函数和类的内部结构)。

1 装饰器

1.1 用装饰器给函数添加一个包装

装饰器的本质是一个能够接收并返回新函数的函数。它可以用来为函数添加额外处理,例如记录日志、计时统计等。在事实上,一个非常常见的应用场景是记录函数的运行时间。

简单的示例:

def CutDown(n):
import time
start = time.time()
while n > 0:
n -= 1
end = time.time()
print(end - start)
CutDown(10000000)

输出结果:

1.1250569820404053秒

引入装饰器的方法:

def GetRunTime(func):
import time
from functools import wraps
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end - start)
return result
return wrapper
@GetRunTime
def cutdown(n):
while n > 0:
n -= 1
cutdown(10000000)

输出结果:

cutdown 1.1274616718292236秒

用这种方法的优势在于,只需为需要记录运行时间的函数添加装饰器即可,极大地简化了调试过程。

1.2 运用装饰器时保存函数的元数据

未使用 @wraps(func) detectives 的话,被装饰函数会失去元数据,如函数名、文档字符串、注解以及调用签名。

未使用 wraps 的示例:

def GetRunTime(func):
import time
def wrapper(*args, **kwargs):
"""参数描述:args、kwargs;返回:函数结果"""
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end - start)
return result
return wrapper
@GetRunTime
def cutdown(n):
"""参数描述:n;返回:None"""
while n > 0:
n -= 1
cutdown(10000000)
print(cutdown.__name__)
print(cutdown.__doc__)

注意:

打印输出结果为:

wrapper 1.4844520092010498秒
wrapper :参数描述:args;返回:None

使用 @wraps(func) 后的示例:

from functools import wraps
def GetRunTime(func):
import time
@wraps(func)
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(func.__name__, end - start)
return result
return wrapper
@GetRunTime
def cutdown(n):
"""参数描述:n;返回:None"""
while n > 0:
n -= 1
print(cutdown.__name__) # 输出:cutdown
print(cutdown.__doc__) # 输出:参数描述:n;返回:None

输出结果示例:

cutdown 1.193265676498413秒
cutdown :参数描述:n;返回:None

可以看出,使用 @wraps(func) 后,函数的元数据完整保留。

1.3 对装饰器进行解包

可以通过 wrapped 属性解包装后的函数。例如:

@GetRunTime
def cutdown(n):
"""参数描述:n;返回:None"""
print('cutdown is running')
while n > 0:
n -= 1
# 使用 wrapped 属性调用原函数
print(cutdown.__wrapped__(10000000))

输出结果:

cutoff is running

这种方法特别有用,当函数有多个装饰器时,可以直接访问被装饰后的函数。

上一篇:python学习笔记4.1-python高级之生成器
下一篇:python学习笔记3.3-高级函数技巧

发表评论

最新留言

路过,博主的博客真漂亮。。
[***.116.15.85]2025年04月22日 02时52分52秒