问题
I'm having some real trouble with timing a function from within an instance of a class. I'm not sure I'm going about it the right way (never used timeIt before) and I tried a few variations of the second argument importing things, but no luck. Here's a silly example of what I'm doing:
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()
Which, when ran, complains about 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
This has to do with TimeIt creating a little virtual environment to run the function in but what do I have to pass to the second argument to make it all happy?
回答1:
if you're willing to consider alternatives to timeit
, i recently found the stopwatch timer utility which might be useful in your case. it's really simple and intuitive, too:
import stopwatch
class TimedClass():
def __init__(self):
t = stopwatch.Timer()
# do stuff here
t.stop()
print t.elapsed
回答2:
Why do you want the timing inside the class being timed itself? If you take the timing out of the class, you can just pass a reference. I.e.
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()
(of course the class itself is redundant, I assume you have a complexer use-case where a simple method is not sufficient).
In general, just pass a callable that has all setup contained/configured. If you want to pass strings to be timed they should contain all necessary setup inside them, i.e.
timeit.Timer("[str(x) for x in range(100)]").timeit()
If you really, really need the timing inside the class, wrap the call in a local method, i.e.
def __init__(self, ..):
def timewrapper():
return self.multiply(self.x, self.y)
timeit.Timer(timewrapper)
回答3:
To address your initial error, you can use timeit within a class with parameters like this:
t = timeit.Timer(lambda: self.square(self.x, self.y)).timeit()
回答4:
(posting as an answer because the code markup does not work in a comment)
I would add a try/finally closure for additional safety:
class TimedClass():
def __init__(self):
t = stopwatch.Timer()
try:
# do stuff here, you can even use return "foo" here and throw exceptions
finally:
t.stop()
print t.elapsed
来源:https://stackoverflow.com/questions/3609148/python-timeit-within-a-class