测量时间的Python上下文管理器
我正在努力制作一段代码,允许测量“with”语句中花费的时间,并将测量的时间(浮点)分配给“with”语句中提供的变量测量时间的Python上下文管理器,python,with-statement,Python,With Statement,我正在努力制作一段代码,允许测量“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 w
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方法中分配新值的方法
更详细地了解contect manager的工作原理,但我不了解其中的大部分。几乎解决了。结果变量是可强制的,并可转换为浮点(但不是浮点本身)
您无法将时间分配给
t
。如PEP中所述,您在As
子句中指定的变量(如果有)将被分配调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
的结果,而不是\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。换句话说,t
仅在with
块的开头分配,而不是在末尾分配
您可以做的是更改\uuuu退出\uuuu
,这样它不返回值,而是执行self.t=time.clock()-self.t
。然后,在with
块完成后,上下文管理器的t
属性将保存经过的时间
要使其正常工作,您还需要从\uuuu\uuu\uuu
返回self
,而不是1
。不确定使用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的值。这里是使用
输出:
执行时间:1.0014秒@ArekBulski:就像我说的,那是不可能的。as
行中的变量仅在开头的with
处赋值一次。政治公众人物对此进行了描述。with
语句旨在让上下文管理器管理with
块中发生的代码上下文。你可以摆弄上下文管理器并在其上存储数据,但它不能以你似乎想要的方式修改周围的环境。@ArekBulski:你能解释一下为什么它的这一方面对你如此重要吗?无论你打算用t
做什么,只要用t.t
就行了。这没什么大不了的。它看起来更漂亮:)Python习语中有一半是关于使事情变得漂亮的。你可以有一个属性。seconds
或。total_seconds
,我认为这更漂亮catchtime
不能是float
,因为float是不可变的,但当上下文退出时你想更改它。您可以实现float接口(请参见dir(float)
)并(主要)像float一样工作,但即使这样,当需要dict
键之类的不可变对象时,您也会遇到问题。我认为与float的协同是最接近理想的。这非常简洁,非常有用。谢谢。还使用perf_counter(),这比time.clock()更好。为什么这不在标准库中?这是《20个你不使用(但应该使用)的Python库》一书中的例子吗?
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)
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")