On Mon, 01 Dec 2008 19:06:24 -0600, Robert Kern wrote: > As Neal has observed, there is a performance hit for creating functions > inside of another function.
True, but it's not a big hit, and I believe it is constant time regardless of the size of the function. The inner function has been (mostly) pre-compiled into bits, and assembling the bits is quite fast. On my desktop, I measure the cost of assembling the inner function to be around the same as two function lookups and calls. >>> def outer(): ... def inner(): ... return None ... return inner() ... >>> def ginner(): ... return None ... >>> def gouter(): ... return ginner() ... >>> from timeit import Timer >>> t1 = Timer('outer()', 'from __main__ import outer') >>> t2 = Timer('gouter()', 'from __main__ import gouter, ginner') >>> t1.repeat() [1.782930850982666, 0.96469783782958984, 0.96496009826660156] >>> t2.repeat() [1.362678050994873, 0.77759003639221191, 0.58583498001098633] Not very expensive. > Every time you go through the outer > function, you are creating new function objects for all of the inner > functions. That's how you can get lexical scoping. It is not equivalent > to defining the functions all at the top-level, where all of the > function objects are created at once. The compiler can't optimize that > overhead away because the overhead arises from implementing a real > feature. But the time it takes to parse the function and compile it to code is optimized away. >>> outer.func_code.co_consts (None, <code object inner at 0xb7e80650, file "<stdin>", line 2>) Which makes me wonder, is there anything we can do with that code object from Python code? I can disassemble it: >>> import dis >>> dis.dis(outer.func_code.co_consts[1]) 3 0 LOAD_CONST 0 (None) 3 RETURN_VALUE Anything else? -- Steven -- http://mail.python.org/mailman/listinfo/python-list