I am currently learning Python pointers and I am having trouble wrapping my head around them. Let's say that you have a function that creates other functions like this:
def create_function(data):
def new_function(other_data):
if data.member == 0:
other_data.member = 1
return new_function
test_func = create_function(object)
How would this work, since the function pointer is only able to access the data while inside the scope of create_function()? Is it only callable within the context of the containing function, or does the function object keep a reference to this data?
CodePudding user response:
The function keeps a reference to this data. (This kind of thing, a function along with "captured" variables is often called a closure).
From the function definitions section of the language reference:
Programmer’s note: Functions are first-class objects. A “def” statement executed inside a function definition defines a local function that can be returned or passed around. Free variables used in the nested function can access the local variables of the function containing the def. See section Naming and binding for details.
CodePudding user response:
python will look up for names in the sequence of local, enclosed, global and finally build-ins. in this case new_function is enclosed in create_function, so new_function will find data in create_function.
CodePudding user response:
A closure is function object that remembers values in enclosing scope .
- It stores function with enclosing environment.
- A closure—unlike a plain function—allows the function to access those captured variables through the closure’s copies of their values or references, even when the function is invoked outside their scope.
CodePudding user response:
I assume you're coming from a C background since you mentioned function pointers.
In C, a function has access to all variables in scope. This most often includes local variables declared within it as well as any arguments the function is specified to receive. More subtly, it also includes global variables which are declared in the outermost scope. Global variables are the closest analogue to what's happening here. Functions have access to them even though they're outside the function.
In C, the addresses of all global variables are known during compilation. When the function accesses this variable, it uses this address. It is static. Also, it is not possible to create new functions or variables at runtime. The variables the compiler observed cannot change.
In dynamic languages that support closures, the functions and variables are created dynamically. You can write code to generate new functions for you. You can have a function that accepts parameters specifying how the new function should behave and then generates and returns it for you. It's as if your C program had a C compiler embedded into it that could generate new functions on the fly.
In order to support these powerful features, the function must store a reference to all variables in scope, just like how the C compiler does internally. So while in C a compiled function can be nearly fully described by a simple function pointer, in Python functions are objects with a pointer to the code that will run as well as pointers to all variables in scope at the time they were created.
When the function is created, we say the variables have been captured. How these variables can change is determined by their scopes and who has access to them. Note that function scopes end when they return. If no other function captures those variables, they won't be referenced again.
Let's break down an example:
z = 0
def f(x):
def g(y):
return x y z
return g
f(1)(2)
Here's whar's happening in this code:
zis a variable in global or file scope.It's visible to everything below it.
fis defined when execution reaches this line.It captures the
zvariable. Changingzglobally will change how the function behaves. This is possible because other code also has access tozdue to its global scope.xis not bound at this time. It only has value when the function is called.gis defined whenfis called.It also captures
z.Since
xhas now been bound to a value, it captures that too. This happens even though it is a local variable that will change every timefis called. Every new instance ofgwill store a reference to thexpassed to the invocation offthat created it. It can be a different value every time.yonly has value whengis called.fis called with1as argument.This creates and returns a new
gfunction with a reference to globalzand localx.Since
ffinishes executing and returns, the scope containingxis rendered inaccessible.gis now the only scope referencing thisxvariable. It can never be changed from outside that scope.The new
gis returned and called with2as argument.Finally, a result is calculated.
zrefers to a global variable.xrefers to the parameter in the particular invocation offthat created thisg.yis the argument to the function.They resolve to
0 1 2and the result is3.
