我有一个字段为spent_times
的课程。 spent_times
是一个列表,此类的所有方法都会写一些信息,这对于日志记录很有用。
另外,我有一个装饰器,它计算每个函数的执行时间并将其写入spent_times
。
这是我的装饰者的实现:
def timing(message):
def wrap(function):
def called(*args, **kwargs):
time_start = timer()
spent_time = round(timer() - time_start, 5)
if not args:
return function(*args, **kwargs), spent_time
obj = args[0]
if hasattr(obj, "spent_times"):
obj.spent_times.append("{}={:.5f}".format(message, spent_time))
return function(*args, **kwargs)
else:
logging.warning('Decorator allows to set spent_time attribute!')
return called
return wrap
正如你在装饰器中看到的那样,如果调用函数具有属性 self ,则会进行检查。
如果有,我可以在现场列表spent_times
中编写所需信息,如果没有,则装饰器返回执行和功能本身所花费的时间。
我在一个单独的模块中使用这个装饰器,第二种情况(当没有找到 self 时)属于这个模块中的一些其他函数,它们不属于类,其中定义了spend_time列表,但我执行了里面我的班级,所以我能够实现以下结构:
这是“外部”功能的声明
def calc_users(requests, priority):
# .....
在我的课程中,我执行它并以这种方式更新我的spend_time列表:
response, spent_time = calc_users(requests, priority)
self.class_obj.spent_times.append("user_calculation={:.5f}".format(spent_time))
这不是很好,但它至少起作用了。
现在,我在不同的新模块中移动了我的类的一些函数,我想使用相同的装饰器时序。
有人可以帮助我在新模块中实现这种时序实现。我不知道,我现在可以做些什么来更新我的spent_times
列表。
这两个模块将同时工作,我不能创建类的对象并将其作为参数传递给新模块,因为(据我所知)将有两个对象,并且将不会正确更新spent_times 。
也许有办法以某种方式传递对spent_times
的引用,但我不想在新模块中更改我的函数的参数,因为我认为在这种情况下共享责任的原则将被打破(装饰器)负责记录,为其行动起作用。)
那么如何改进装饰器或如何将spent_times
列表传递给新模块?
任何帮助都将非常感谢!
P.S。
也许让spent_times
成为一个全局变量? (在最糟糕的情况下)
答案 0 :(得分:1)
全局列表似乎很好,但您也可以通过在实例化后删除类来使用类并创建单例。这可以防止创建另一个实例:
# mymodule.py
from timeit import default_timer as timer
class Timing(object):
def __init__(self):
self.spent_times = []
def __call__(self, message):
def wrap(function):
def called(*args, **kwargs):
time_start = timer()
spent_time = round(timer() - time_start, 5)
self.spent_times.append("{}={:.5f}".format(message, spent_time))
return function(*args, **kwargs)
return called
return wrap
timing = Timing()
del Timing # prevent another instance
现在导入另一个模块:
from mymodule import timing
@timing('Hello')
def add(a, b):
return a + b
特殊方法__call__
使类的实例表现得像一个函数,即它可以用()
调用。
您可以使用self.attr
而不是全局变量的优势。
实例化后删除类会阻止创建另一个实例。这被称为单身人士。现在,无论您使用timing
作为装饰器的频率如何,所有时间都会在同一个列表中结束。