Is there an overhead when nesting functions in Python? Is there an overhead when nesting functions in Python? python python

Is there an overhead when nesting functions in Python?


The code object is pre-compiled so that part has no overhead. The function object gets built on every invocation -- it binds the function name to the code object, records default variables, etc.

Executive summary: It's not free.

>>> from dis import dis>>> def foo():        def bar():                pass        return bar>>> dis(foo)  2           0 LOAD_CONST               1 (<code object bar at 0x1017e2b30, file "<pyshell#5>", line 2>)              3 MAKE_FUNCTION            0              6 STORE_FAST               0 (bar)  4           9 LOAD_FAST                0 (bar)             12 RETURN_VALUE 


Yes, a new object would be created each time. It's likely not an issue unless you have it in a tight loop. Profiling will tell you if it's a problem.

In [80]: def foo():   ....:     def bar():   ....:         pass   ....:     return bar   ....: In [81]: id(foo())Out[81]: 29654024In [82]: id(foo())Out[82]: 29651384


There is an impact, but in most situations it is so small that you shouldn't worry about it - most non-trivial applications probably already have performance bottlenecks whose impacts are several orders of magnitude larger than this one. Worry instead about the readability and reusability of the code.

Here some code that compares the performance of redefining a function each time through a loop to reusing a predefined function instead.

import gcfrom datetime import datetimeclass StopWatch:     def __init__(self, name):         self.name = name     def __enter__(self):         gc.collect()         self.start = datetime.now()     def __exit__(self, type, value, traceback):         elapsed = datetime.now()-self.start         print '** Test "%s" took %s **' % (self.name, elapsed)def foo():     def bar():          pass     return bardef bar2():    passdef foo2():    return bar2num_iterations = 1000000with StopWatch('FunctionDefinedEachTime') as sw:    result_foo = [foo() for i in range(num_iterations)]with StopWatch('FunctionDefinedOnce') as sw:    result_foo2 = [foo2() for i in range(num_iterations)]

When I run this in Python 2.7 on my Macbook Air running OS X Lion I get:

** Test "FunctionDefinedEachTime" took 0:00:01.138531 **** Test "FunctionDefinedOnce" took 0:00:00.270347 **