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:
z
is a variable in global or file scope.It's visible to everything below it.
f
is defined when execution reaches this line.It captures the
z
variable. Changingz
globally will change how the function behaves. This is possible because other code also has access toz
due to its global scope.x
is not bound at this time. It only has value when the function is called.g
is defined whenf
is called.It also captures
z
.Since
x
has now been bound to a value, it captures that too. This happens even though it is a local variable that will change every timef
is called. Every new instance ofg
will store a reference to thex
passed to the invocation off
that created it. It can be a different value every time.y
only has value wheng
is called.f
is called with1
as argument.This creates and returns a new
g
function with a reference to globalz
and localx
.Since
f
finishes executing and returns, the scope containingx
is rendered inaccessible.g
is now the only scope referencing thisx
variable. It can never be changed from outside that scope.The new
g
is returned and called with2
as argument.Finally, a result is calculated.
z
refers to a global variable.x
refers to the parameter in the particular invocation off
that created thisg
.y
is the argument to the function.They resolve to
0 1 2
and the result is3
.