nested functions

George Sakkis george.sakkis at gmail.com
Thu Jun 15 08:38:10 EDT 2006


Duncan Booth wrote:

> Fredrik Lundh wrote:
>
> > George Sakkis wrote:
> >
> >> It shouldn't come as a surprise if it turns out to be slower, since
> >> the nested function is redefined every time the outer is called.
> >
> > except that it isn't, really: all that happens is that a new function
> > object is created from prebuilt parts, and assigned to a local
> > variable.  it's not slower than, say, a method call.
> >
> It looks to be somewhat faster than a method call:
>
> C:\temp>\python24\lib\timeit.py -s "import t" "t.testMethod(t.instance,
> 42)"
> 1000 loops, best of 3: 1.58 msec per loop
>
> C:\temp>\python24\lib\timeit.py -s "import t" "t.testMethod2(t.instance,
> 42)"
> 100 loops, best of 3: 1.61 msec per loop
>
> C:\temp>\python24\lib\timeit.py -s "import t" "t.testNested(t.instance,
> 42)"
> 1000 loops, best of 3: 1.06 msec per loop
>
> C:\temp>\python24\lib\timeit.py -s "import t" "t.testNested2(t.instance,
> 42)"
> 1000 loops, best of 3: 1.08 msec per loop
>
> C:\temp>\python24\lib\timeit.py -s "import t" "t.testNested3(t.instance,
> 42)"
> 1000 loops, best of 3: 1.13 msec per loop
>
> C:\temp>\python24\lib\timeit.py -s "import t" "t.testNested4(t.instance,
> 42)"
> 1000 loops, best of 3: 1.23 msec per loop
>
>
> --------- t.py -------------
> class C:
>     def m1(self):
>         return 42
>
>     def m2(self, x):
>         return x
>
> instance = C()
>
> def testMethod(instance,x):
>     n = 0
>     while n < 100000:
>         n += instance.m1()
>
> def testMethod2(instance, x):
>     n = 0
>     while n < 100000:
>         n += instance.m2(x)
>
> def testNested(instance, x):
>     def m1():
>         return 42
>     n = 0
>     while n < 100000:
>         n += m1()
>
> def testNested2(instance, x):
>     def m2():
>         return x
>     n = 0
>     while n < 100000:
>         n += m2()
>
> def testNested3(instance, x):
>     def m2(y):
>         return y
>     n = 0
>     while n < 100000:
>         n += m2(x)
>
> def testNested4(instance, x):
>     def m2(y):
>         return x
>     n = 0
>     while n < 100000:
>         n += m2(x)
>
> ----------------------------
>
> The differences between the nested function calls show how difficult it can
> be guessing what will be faster: #3&#4 show that all, else being equal,
> accessing the closure is much slower than accessing a parameter, but #2
> shows that not passing any parameters to the nested function more than
> compensates for the single slow closure access.

It would also be interesting to add unnested versions of m1(), m2()
(functions, not methods) to the comparison.

George




More information about the Python-list mailing list