When Closure get external variable's value?

Discussion in 'Python' started by Huayang Xia, Dec 18, 2006.

  1. Huayang Xia

    Huayang Xia Guest

    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.
    Huayang Xia, Dec 18, 2006
    #1
    1. Advertising

  2. Huayang Xia

    Huayang Xia Guest

    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?
    Huayang Xia, Dec 18, 2006
    #2
    1. Advertising

  3. 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
    Jussi Salmela, Dec 18, 2006
    #3
  4. Huayang Xia

    Huayang Xia Guest

    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.
    Huayang Xia, Dec 19, 2006
    #4
  5. 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>
    Fredrik Lundh, Dec 19, 2006
    #5
  6. Huayang Xia

    Huayang Xia Guest

    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 <> wrote:
    > 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>
    Huayang Xia, Dec 19, 2006
    #6
  7. In <>, 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
    Marc 'BlackJack' Rintsch, Dec 19, 2006
    #7
  8. Huayang Xia

    Huayang Xia Guest

    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.
    Huayang Xia, Dec 19, 2006
    #8
  9. 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.
    Bruno Desthuilliers, Dec 19, 2006
    #9
  10. 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>
    Fredrik Lundh, Dec 19, 2006
    #10
  11. Huayang Xia

    Huayang Xia Guest

    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
    <> wrote:
    > 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.
    Huayang Xia, Dec 19, 2006
    #11
  12. 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>
    Fredrik Lundh, Dec 19, 2006
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Robert Klemme

    local variable and closure

    Robert Klemme, Jan 30, 2006, in forum: Ruby
    Replies:
    3
    Views:
    143
    Schüle Daniel
    Jan 30, 2006
  2. Julian Mehnle
    Replies:
    0
    Views:
    227
    Julian Mehnle
    Jul 17, 2003
  3. Jake Barnes
    Replies:
    2
    Views:
    296
  4. Closure variable bindings

    , Nov 15, 2007, in forum: Javascript
    Replies:
    6
    Views:
    99
  5. Replies:
    3
    Views:
    92
    Terry Reedy
    Aug 18, 2013
Loading...

Share This Page