[TIP] Interesting getattr pattern [was: Re: [issue5728] Support telling TestResult objects a test run has finished]
Olemis Lang
olemis at gmail.com
Tue Apr 14 09:56:53 PDT 2009
On Mon, Apr 13, 2009 at 9:10 AM, Olemis Lang <olemis at gmail.com> wrote:
>
> According to my experience, function calls are expensive, especially
> in this case where startTestRun method can be called *MANY* times.
>
I tried to measure the three candidate alternatives. I employed a
simpler example (didnt remember the whole code :-/ , and this was done
yesterday ) :
{{{
#!python
class A():
def method(self):
pass
class B():
pass
REPEAT = 100000
def func1(x):
for _ in xrange(REPEAT):
try:
method = x.method
except AttributeError:
pass
else:
method()
def func2(x):
for _ in xrange(REPEAT):
method = getattr(x, 'method', None)
if method is not None:
method()
def func3(x):
for _ in xrange(REPEAT):
method = getattr(x, 'method', lambda : None)
method()
}}}
Here you have the results :
{{{
>>> from cProfile import run
>>> run('func1(A())')
100003 function calls in 0.395 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.238 0.238 0.395 0.395 <stdin>:1(func1)
100000 0.157 0.000 0.157 0.000 <stdin>:2(method)
1 0.000 0.000 0.395 0.395 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of
'_lsprof.Profiler' objects}
>>> run('func1(B())')
3 function calls in 0.446 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.446 0.446 0.446 0.446 <stdin>:1(func1)
1 0.000 0.000 0.446 0.446 <string>:1(<module>)
1 0.000 0.000 0.000 0.000 {method 'disable' of
'_lsprof.Profiler' objects}
>>> run('func2(A())')
200003 function calls in 0.720 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.404 0.404 0.720 0.720 <stdin>:1(func2)
100000 0.155 0.000 0.155 0.000 <stdin>:2(method)
1 0.000 0.000 0.720 0.720 <string>:1(<module>)
100000 0.161 0.000 0.161 0.000 {getattr}
1 0.000 0.000 0.000 0.000 {method 'disable' of
'_lsprof.Profiler' objects}
>>> run('func2(B())')
100003 function calls in 0.711 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.256 0.256 0.711 0.711 <stdin>:1(func2)
1 0.000 0.000 0.711 0.711 <string>:1(<module>)
100000 0.455 0.000 0.455 0.000 {getattr}
1 0.000 0.000 0.000 0.000 {method 'disable' of
'_lsprof.Profiler' objects}
>>> run('func3(A())')
200003 function calls in 0.852 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.550 0.550 0.852 0.852 <stdin>:1(func3)
100000 0.149 0.000 0.149 0.000 <stdin>:2(method)
1 0.000 0.000 0.852 0.852 <string>:1(<module>)
100000 0.154 0.000 0.154 0.000 {getattr}
1 0.000 0.000 0.000 0.000 {method 'disable' of
'_lsprof.Profiler' objects}
>>> run('func3(B())')
200003 function calls in 1.022 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.442 0.442 1.022 1.022 <stdin>:1(func3)
100000 0.148 0.000 0.148 0.000 <stdin>:3(<lambda>)
1 0.000 0.000 1.022 1.022 <string>:1(<module>)
100000 0.432 0.000 0.432 0.000 {getattr}
1 0.000 0.000 0.000 0.000 {method 'disable' of
'_lsprof.Profiler' objects}
}}}
Possible conclusions :
- func1 seems to be the fastest
- func2 seems to be quite cool
- func3 seems to be the slowest
... from there on it's up to you anyway.
--
Regards,
Olemis.
Blog ES: http://simelo-es.blogspot.com/
Blog EN: http://simelo-en.blogspot.com/
Featured article:
More information about the testing-in-python
mailing list