When Closure get external variable's value?

H

Huayang Xia

What will the following piece of code print? (10 or 15)

def testClosure(maxIndex) :

def closureTest():
return maxIndex

maxIndex += 5

return closureTest()

print testClosure(10)

My question is when the closure function gets value for maxindex? Run
time or compile time?

Thanks.
 
H

Huayang Xia

It will print 15. The closure gets the value at run time.

Could we treat closure as part of the external function and it shares
the local variable with its holder function?
 
J

Jussi Salmela

Huayang Xia kirjoitti:
It will print 15. The closure gets the value at run time.

Could we treat closure as part of the external function and it shares
the local variable with its holder function?

I don't quite get what you are trying to tell us but if you think that
in your example code:

def testClosure(maxIndex) :

def closureTest():
return maxIndex

maxIndex += 5

return closureTest()

print testClosure(10)

you are returning a callable function you are all wrong. This can be
easily seen by:
15
<type 'int'>

The mistake is that you shouldn't return closureTest() but closureTest
instead. The correct way would be:
def closureTest():
return maxIndex
maxIndex += 5
return closureTest
15

Cheers,
Jussi
 
H

Huayang Xia

Thanks for the clarification.

But my question is:

When does the closure get the value of the maxIndex in the following
code snippet?

def testClosure(maxIndex) :

def closureTest():
return maxIndex

maxIndex += 5

return closureTest()

print testClosure(10)


I thought it should be 10 instead of 15. That was wrong.

After several tests, I found maxIndex is, though, local to
testClosure() but is external to the closureTest(). closureTest() gets
the value of maxIndex at run time. So that it's 15 instead of 10. The
following snippet will verify that further:

def testClosure1(lst):

def closureTest():
lst.append(lst[-1]+1)

lst.append(lst[-1]+1)
return closureTest()

alist = [1]
testClosure1(alist)
alist.append(3)
testClosure1(alist)

The 'lst' in function testClosure1() and the closure closureTest() are
same thing as alist. So everything is dynamic. Variable's value is
determined at run time.
 
F

Fredrik Lundh

Huayang said:
When does the closure get the value of the maxIndex in the following
code snippet?

def testClosure(maxIndex) :

def closureTest():
return maxIndex

maxIndex += 5

return closureTest()

print testClosure(10)


I thought it should be 10 instead of 15. That was wrong.

free variables in an inner scope bind to variables in the outer scope,
not objects.

if you want to bind to objects, use explicit binding:

def closureTest(maxIndex=maxIndex):
return maxIndex

</F>
 
H

Huayang Xia

That is a really concise and precise answer. Thanks.

So the object binding can only happen explicitly at the closure
declaration argument list(non-free variable).
 
M

Marc 'BlackJack' Rintsch

Huayang Xia said:
That is a really concise and precise answer. Thanks.

So the object binding can only happen explicitly at the closure
declaration argument list(non-free variable).

That's no declaration that's a definition and it happens at runtime! It's
executed every time the outer function is called and executed and creates
a function object.

As far as I can see you don't create a closure BTW. You are *calling*
that inner function and return the *result* of that call.

Ciao,
Marc 'BlackJack' Rintsch
 
H

Huayang Xia

I'm confused. What is the definition of closure.

I'm not sure if it's correct, I get the definition from wikipedia:

"A closure typically comes about when one function is declared entirely
within the body of another, and the inner function refers to local
variables of the outer function. At runtime, when the outer function
executes, a closure is formed. It consists of the inner function's code
and references to any variables in the outer function's scope that the
closure needs."

I agree it is not declaration, it's definition. However it's closure
based on the above definition. It uses free variable. Or you mean it's
a closure only when the outer function returns it and be exposed to
external world?

The code snippet was just for test purpose. My question was how the
free variable inside inner function (the closure) binds with object.
That was answered by Fredrik perfectly.
 
B

Bruno Desthuilliers

Huayang Xia a écrit :
I'm confused. What is the definition of closure.
>
I'm not sure if it's correct, I get the definition from wikipedia:

"A closure typically comes about when one function is declared entirely
within the body of another, and the inner function refers to local
variables of the outer function. At runtime, when the outer function
executes, a closure is formed. It consists of the inner function's code
and references to any variables in the outer function's scope that the
closure needs."

You skipped the first and most important sentence:
"In programming languages, a closure is a function that refers to free
variables in its lexical context."

IOW, a closure is a function that carry it's own environment. In the
following code, the function returned by make_adder is a closure :

def make_adder(adding):
def adder(num):
return num + adding
return adder


add_three = make_adder(3)
print add_three(4)
=> 7
I agree it is not declaration, it's definition. However it's closure
based on the above definition. It uses free variable.

Actually, it uses a variable defined in the enclosing scope. But as long
as it's also executed in the same enclosing scope, it's just a nested
function.
Or you mean it's
a closure only when the outer function returns it and be exposed to
external world?

Bingo.
 
F

Fredrik Lundh

"In programming languages, a closure is a function that refers to free
variables in its lexical context."

IOW, a closure is a function that carry it's own environment.

in contrast to functions that don't know what environment they belong
to, you mean ? can you identify such a construct in Python ?

</F>
 
H

Huayang Xia

My understanding was:

Closure is a nested function first. If it refers free variable, then it
is closure. If it doesn't refer free variable, it doesn't have to be
nested. That is probably the reason, the free variable is emphasized.
Normally it makes sense to return a closure, but not a non-closure
nested function.

I don't understand why while a nested function perfectly matches the
definition of closure, it is not closure simply because it is not used
by external world.

BTW, IMHO, The meaning of the "most important sentence" was contained
in the original quote. That was the reason I skipped it.
 
F

Fredrik Lundh

Huayang said:
I don't understand why while a nested function perfectly matches the
definition of closure, it is not closure simply because it is not used
by external world.

Like so many other computing terms, the word "closure" is used in
different ways by different people.

Strictly speaking, a closure is simply a function with free variables,
where the bindings for all such variables are known in advance. Some
early languages didn't have "closed" functions; the bindings for free
variables were left open, and was determined at runtime. And languages
that had both "open" and "closed" functions needed some way to
distinguish between the two, so people started referring to the latter
as "closures".

But in Python, as well as in most other modern languages, all functions
are "closed" -- i.e. there are no "open" free variables -- so the use of
the term has morphed from "a function for which all free variables have
a known binding" to "a function that can refer to environments that are
no longer active" (such as the local namespace of an outer function,
even after that function has returned). And since *that* is somewhat
difficult to implement, and programmers don't like to hide things that
are hard to implement, people still like to use the term to distinguish
between closed functions of kind 1 and closed functions of kind 2. As
in this thread, they sometimes argue that when you're using a closed
function of kind 2 in a specific way, it's not quite as much of a
closure as when you use it in another way. Heck, some people even argue
that languages that don't support closed functions of kind 3 (a kind
that Python currently doesn't support) don't really have closures at all.

But as a language user, you can actually forget about all this -- all
you need to know is that in Python, all functions are closed, and free
variables bind to *variable names* in lexically nested outer scopes.

</F>
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top