Re: Generators vs. Functions?
- From: bokr@xxxxxx (Bengt Richter)
- Date: Tue, 07 Feb 2006 02:11:41 GMT
On Sun, 05 Feb 2006 19:14:29 +1100, Steven D'Aprano <steve@xxxxxxxxxxxxxxxxxxxxxx> wrote:
On Sun, 05 Feb 2006 03:31:24 +0000, Neil Schemenauer wrote:I show an advantage favoring generator resumption vs function call:
Peter Hansen <peter@xxxxxxxxxxx> wrote:
More precisely, the state of the function is *saved* when a yield
occurs, so you certainly don't *recreate* it from scratch, but merely
restore the state, and this should definitely be faster than creating it
from scratch in the first place.
Right. Resuming a generator is faster than calling a function.
Have you actually measured this, or are you just making a wild guess?
According to a short test performed by Magnus Lycka, resuming a generator
takes more time than calling a function. My own test agrees.
Here is my test, using Python 2.3. I've tried to make the test as fair as
possible, with the same number of name lookups in both pieces of test code.
# straight function, two name lookups
... """class K:import timeit
t1 = timeit.Timer(stmt="func.next()", setup=
... pass
...
... def next():
... return 1
...
... func = K()
... func.next = next
... """)
0.63980388641357422
t1.timeit()
# generator, two name lookups
... """def g():t2 = timeit.Timer(stmt="gen.next()", setup=
... while 1: yield 1
...
... gen = g()
... """)
0.82081794738769531
t2.timeit()
# straight function, one name lookup
... """def f():t3 = timeit.Timer(stmt="f()", setup=
... return 1
... """)
0.47273492813110352
t3.timeit()
# generator, one name lookup
... """def g():t4 = timeit.Timer(stmt="gnext()", setup=
... while 1: yield 1
...
... gnext = g().next
... """)
0.55085492134094238
t4.timeit()
So on the basis of my tests, there is a small, but significant speed
advantage to _calling_ a function versus _resuming_ a generator.
Of course the other advantages of generators often far outweigh the tiny
setup cost each time you call one. In addition, for any complex function
with significant execution time, the call/resume time may be an
insignificant fraction of the total execution time. There is little or no
point in avoiding generators due to a misplaced and foolish attempt to
optimise your code.
...from time import clock
def f(): return clock()
...def g(): yield clock(); yield clock()
-9.2190462142316409e-006max(f()-f() for x in xrange(10000))
-9.2190462139818408e-006max(f()-f() for x in xrange(10000))
-7.5428559682677587e-006max(float.__sub__(*g()) for x in xrange(10000))
-7.5428559682677587e-006max(float.__sub__(*g()) for x in xrange(10000))
-7.5428559682677587e-006max(float.__sub__(*g()) for x in xrange(10000))
(It'll probably go ten times faster on a recent box ;-)
Regards,
Bengt Richter
.
- References:
- Generators vs. Functions?
- From: Wolfgang Keller
- Re: Generators vs. Functions?
- From: Peter Hansen
- Re: Generators vs. Functions?
- From: Neil Schemenauer
- Re: Generators vs. Functions?
- From: Steven D'Aprano
- Generators vs. Functions?
- Prev by Date: Re: Literal Escaped Octets
- Next by Date: Re: * 'struct-like' list *
- Previous by thread: Re: Generators vs. Functions?
- Next by thread: Webmail with Python
- Index(es):
Relevant Pages
|