def outer():
def inner(a):
return a
return inner
f = outer()
print(f) # <function outer.<locals>.inner at 0x1044b61e0>
f2 = outer()
print(f2) # <function outer.<locals>.inner at 0x1044b6268> (Different from above)
I know that f and f2 are different from each other.
But can someone tell me a precise explanation why they are different from each other?
Thank You
CodePudding user response:
The inner
function is defined in the outer
function. A new instance of this function is re-created every time you call outer
.
Consider the following function:
a = 2
def not_so_inner():
return a
You would expect it to always return 2
, since a
is a module variable.
Now, if I write the following function:
def outer(a):
def inner():
return a
return inner
f1 = outer(1)
f2 = outer(2)
f1
and f2
are both a representation of the inner
function, but bound to a different context where the a
variable has a different value.
The return function must carry the outer context, so they are different instances of the function defined in the outer
function.
CodePudding user response:
Observe that without the return
statement involved, the id
of the inner fuction inner
is the same value, when outer()
is called multiple times. This indicates that the inner
function is actually pointing to the same reference value in memory.
>>> def outer():
... print('outer() is being called.')
... class A:
... ...
... def inner(a):
... return a
... print('id of class A:', id(A))
... print('id of function inner():', id(inner))
...
>>> outer()
outer() is being called.
id of class A: 2098069832976
id of function inner(): 2098062549056
>>> outer()
outer() is being called.
id of class A: 2098069814096
id of function inner(): 2098062549056
Notice that the line id of function inner(): ...
indicates that the id
values for inner()
are the same in either case.
When you introduce a return
statement, then things become a little more interesting. It looks like the id
value is different each time, which indicates a new inner()
function is being created on each invocation of outer()
.
def outer():
print('outer() is being called.')
class A:
...
def inner(a):
return a
print(' id of class A:', id(A))
print(' id of function inner():', id(inner))
return inner
inner1 = outer()
inner2 = outer()
inner3 = outer()
print()
print(id(inner1))
print(id(inner2))
print(id(inner3))
Sample output:
outer() is being called.
id of class A: 2175736425280
id of function inner(): 2175746787792
outer() is being called.
id of class A: 2175736423360
id of function inner(): 2175746786496
outer() is being called.
id of class A: 2175736424320
id of function inner(): 2175746788080
2175746787792
2175746786496
2175746788080
Now I'm not entirely sure if this post answers your question, however it is certainly food for thought and for future consideration.
Using the builtin id()
function in Python, you can confirm that a new inner()
function is being created on each run, at least in regards to the second case above.