So AFAIK in CPython, function definitions are compiled into function objects when executed at parse time. But what about inner functions? Do they get compiled into function objects at parse time or do they get compiled (or interpreted) every single time the function is called? Do inner functions incur any performance penalty at all?
So AFAIK in CPython, function definitions are compiled into function objects when executed at
Share
To give a general explaination – assuming you have the following code in a module:
When the file is parsed by python via
compile(), the above text is turned into bytecode for how to execute the module. In the module bytecode, there are two “code objects”, one for the bytecode ofouter()and one for the bytecodeinner(). Note that I said code objects, not functions – the code objects contain little more than the bytecode used by the function, and any information that could be known at compile time – such as the bytecode forouter()containing a ref to the bytecode forinner().When the module actually loads, by evaluating the code object associated with the module, one thing which happens is an actual “function object” is created for
outer(), and stored in the module’souterattribute. The function object acts as a collection of the bytecode and all context-relavant things that are needed to call the function (eg which globals dict it should pull from, etc) that can’t be known at compile time. In a way, a code object is a template for a function, which is a template for execution of the actual bytecode with all variables filled in.None of this involved
inner()-as-a-function yet – Each time you actually get around to callingouter(), that’s when a newinner()function object is created for that invocation of outer, which binds the already-created inner bytecode object to a list of globals, including the value ofxas passed into that call to outer. As you can imagine, this is pretty fast, since no parsing is needed, just filling in a quick struct with some pointers to other already-existing objects.