471,854 Members | 1,786 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,854 software developers and data experts.

When Closure get external variable's value?

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.

Dec 18 '06 #1
11 2869
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?

Dec 18 '06 #2
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:
>>type(testClosure(10))
15
<type 'int'>

The mistake is that you shouldn't return closureTest() but closureTest
instead. The correct way would be:
>>def testClosure2(maxIndex):
def closureTest():
return maxIndex
maxIndex += 5
return closureTest
>>f2 = testClosure2(10)
<function closureTest at 0x00D82530>
>>type(f2)
<type 'function'>
>>print f2()
15

Cheers,
Jussi
Dec 18 '06 #3
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.

Dec 19 '06 #4
Huayang Xia wrote:
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>

Dec 19 '06 #5
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).

On Dec 19, 10:37 am, Fredrik Lundh <fred...@pythonware.comwrote:
Huayang Xia wrote:
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>
Dec 19 '06 #6
In <11**********************@t46g2000cwa.googlegroups .com>, Huayang Xia
wrote:
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
Dec 19 '06 #7
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.

Dec 19 '06 #8
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.
Dec 19 '06 #9
Bruno Desthuilliers wrote:
>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 contrast to functions that don't know what environment they belong
to, you mean ? can you identify such a construct in Python ?

</F>

Dec 19 '06 #10
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.

On Dec 19, 4:14 pm, Bruno Desthuilliers
<bdesth.quelquech...@free.quelquepart.frwrote:
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.
Dec 19 '06 #11
Huayang Xia wrote:
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>

Dec 19 '06 #12

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

27 posts views Thread by Ted Lilley | last post: by
1 post views Thread by mr_burns | last post: by
2 posts views Thread by Harry Stangel | last post: by
reply views Thread by Gerard Brunick | last post: by
2 posts views Thread by Bob.Sidebotham | last post: by
reply views Thread by =?Utf-8?B?SlA=?= | last post: by
3 posts views Thread by disappearedng | last post: by
NeoPa
reply views Thread by NeoPa | last post: by
aboka
reply views Thread by aboka | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.