在Python中使用装饰器函数时,如何获得包装器函数返回的信息?



我正在尝试访问执行一个函数的时间,这个函数是在decorator函数内。

我遵循这篇文章的方向,因为我无法让函数接受我传递给它的参数。现在我不确定如何从调用函数中获得数据。

下面是我的代码:
import time
from functools import wraps
def sort_timer(func):
def outer(func):
@wraps(func)
def inner(*args, **kwargs):
start = time.perf_counter()
func(*args, **kwargs)
finish = time.perf_counter()
return start - finish
return inner
return outer
@sort_timer
def bubble_sort(a_list):
"""Sorts a_list in ascending order"""
for pass_num in range(len(a_list) - 1):
for index in range(len(a_list) - 1 - pass_num):
if a_list[index] > a_list[index + 1]:
temp = a_list[index]
a_list[index] = a_list[index + 1]
a_list[index + 1] = temp
list1 = [60, 19, 22, 14, 43, 27, 3, 77]
x = bubble_sort(list1)
print(x)

返回的似乎是内部函数。以下是记录到控制台的内容:

<function sort_timer.<locals>.outer.<locals>.inner at 0x0000027167770310>

如有任何见解将不胜感激。谢谢你。

您引用的答案中的代码专门用于向装饰器提供参数。只要你把()放在@sort_timer之后,它就会起作用…并且,正如目前所写的,提供一个论证。下面是一个示例,为了清晰起见,将第一个func参数重命名:

def sort_timer(parameter):
def outer(func):
@wraps(func)
def inner(*args, **kwargs):
start = time.perf_counter()
func(*args, **kwargs)
finish = time.perf_counter()
return start - finish
return inner
return outer
@sort_timer(13) # for example
...

也就是说,在您的代码中,如所示,您并没有真正使用双重包装技术来获得任何好处。除非您打算为装饰器本身(而不是被装饰的函数)提供参数,否则您可以这样简化:

def sort_timer(func):
@wraps(func)
def inner(*args, **kwargs):
start = time.perf_counter()
func(*args, **kwargs)
finish = time.perf_counter()
return start - finish
return inner

为什么不像timeit和timing decorator中提到的那样使用一个简单的装饰器来计时呢?

import time
import functools
def timeit(f):
@functools.wraps(f)
def timed(*args, **kw):
ts = time.time()
result = f(*args, **kw)
te = time.time()
print(f"func:{f.__name__} args:{args}{'' if len(kw) == 0 else kw} took: {(te-ts)*1000 :.3f} msec")
return result
return timed
@timeit
def bubble_sort(a_list):
"""Sorts a_list in ascending order"""
for pass_num in range(len(a_list) - 1):
for index in range(len(a_list) - 1 - pass_num):
if a_list[index] > a_list[index + 1]:
temp = a_list[index]
a_list[index] = a_list[index + 1]
a_list[index + 1] = temp
list1 = [60, 19, 22, 14, 43, 27, 3, 77]
x = bubble_sort(list1)

打印:

func:bubble_sort args:([3, 14, 19, 22, 27, 43, 60, 77],) took: 0.029 msec

@functools.wraps(f)f的元信息复制到修饰函数timed中,使修饰函数保留了原/目标函数的特征。

下面是计算函数执行时间的代码:

import time

def timer(func):
def wrapper(*args, **kwargs):
start = time.time()
func(*args, **kwargs)
end = time.time() - start
print(end)
return wrapper