我正在努力制作一段代码,允许测量在“with”语句中花费的时间,并将测量的时间(浮点数)分配给“with”语句中提供的变量。
import time
class catchtime:
def __enter__(self):
self.t = time.clock()
return 1
def __exit__(self, type, value, traceback):
return time.clock() - self.t
with catchtime() as t:
pass
此代码离开t=1
而不是clock()调用之间的区别。如何解决这个问题?我需要一种从exit方法中分配新值的方法。
PEP 343 describes更详细地说明了竞赛经理是如何运作的,但我不了解其中的大部分内容。
答案 0 :(得分:4)
解决了(差不多)。结果变量是可强制的并且可以转换为浮点数(但不是浮点数)。
class catchtime:
def __enter__(self):
self.t = time.clock()
return self
def __exit__(self, type, value, traceback):
self.e = time.clock()
def __float__(self):
return float(self.e - self.t)
def __coerce__(self, other):
return (float(self), other)
def __str__(self):
return str(float(self))
def __repr__(self):
return str(float(self))
with catchtime() as t:
pass
print t
print repr(t)
print float(t)
print 0+t
print 1*t
1.10000000001e-05
1.10000000001e-05
1.10000000001e-05
1.10000000001e-05
1.10000000001e-05
答案 1 :(得分:4)
您无法将时间分配给t
。如PEP中所述,您在as
子句中指定的变量(如果有)将被分配调用__enter__
的结果,而不是__exit__
。换句话说,t
仅在with
块的 start 处分配,而不是在末尾。
您可以做的是更改__exit__
,以便不是返回值,而是self.t = time.clock() - self.t
。然后,在with
块完成后,上下文管理器的t
属性将保留已用时间。
为了实现这一目标,您还希望从self
返回1
而不是__enter__
。使用1
确定您要实现的目标。
所以它看起来像这样:
class catchtime(object):
def __enter__(self):
self.t = time.clock()
return self
def __exit__(self, type, value, traceback):
self.t = time.clock() - self.t
with catchtime() as t:
time.sleep(1)
print(t.t)
打印出一个非常接近1的值。
答案 2 :(得分:2)
以下是使用contextmanager
的示例from time import perf_counter
from contextlib import contextmanager
@contextmanager
def catchtime() -> float:
start = perf_counter()
yield lambda: perf_counter() - start
with catchtime() as t:
import time
time.sleep(1)
print(f"Execution time: {t():.4f} secs")
输出:
执行时间:1.0014秒