Python - 类内使用Timeit

9 投票
5 回答
11663 浏览
提问于 2025-04-16 03:31

我在一个类的实例中计时一个函数时遇到了一些麻烦。我不太确定自己是不是在正确的方式上(之前从没用过timeIt),我尝试了几种不同的方式来导入第二个参数,但都没有成功。下面是我正在做的一个简单例子:

import timeit

class TimedClass():
    def __init__(self):
        self.x = 13
        self.y = 15
        t = timeit.Timer("self.square(self.x, self.y)")
        try:
            t.timeit()
        except:
            t.print_exc()

    def square(self, _x, _y):
        print _x**_y

myTimedClass = TimedClass()

运行这个代码时,它会抱怨关于self的问题。

Traceback (most recent call last):
  File "timeItTest.py", line 9, in __init__
    t.timeit()
  File "C:\Python26\lib\timeit.py", line 193, in timeit
    timing = self.inner(it, self.timer)
  File "<timeit-src>", line 6, in inner
    self.square(self.x, self.y)
NameError: global name 'self' is not defined

这和TimeIt创建了一个小的虚拟环境来运行这个函数有关,但我需要给第二个参数传什么才能让它正常工作呢?

5 个回答

8

要解决你最开始遇到的错误,你可以在一个类里面使用timeit,并且可以像这样传入参数:

 t = timeit.Timer(lambda: self.square(self.x, self.y)).timeit()
9

你为什么想要在类里面自己计时呢?如果把计时功能放到类外面,你可以直接传一个引用进去。也就是说:

import timeit

class TimedClass():
    def __init__(self):
        self.x = 13
        self.y = 15

    def square(self, _x, _y):
        print _x**_y

myTimedClass = TimedClass()
timeit.Timer(myTImedClass.square).timeit()

(当然,这个类本身可能有点多余,我猜你有更复杂的情况,简单的方法不够用)。

一般来说,直接传一个可以调用的东西,里面包含所有的设置和配置。如果你想传字符串来计时,它们应该自己包含所有必要的设置,也就是说:

timeit.Timer("[str(x) for x in range(100)]").timeit()

如果你真的非常需要在类里面进行计时,可以把调用包裹在一个本地方法里,也就是说:

def __init__(self, ..):
    def timewrapper():
        return self.multiply(self.x, self.y)

    timeit.Timer(timewrapper)
10

如果你愿意考虑一些替代方案来代替 timeit,我最近发现了一个叫做 stopwatch 的计时工具,这可能对你有帮助。它非常简单易用,直观明了:

import stopwatch

class TimedClass():

    def __init__(self):
        t = stopwatch.Timer()
        # do stuff here
        t.stop()
        print t.elapsed

撰写回答