top | item 2919984

(no title)

carbonica | 14 years ago

I'm sorry? Python is the same way:

    >>> i = 10
    >>> def x():
    ...   print i
    ... 
    >>> x()
    10
    >>> i = 11
    >>> x()
    11
The value is not closed over in any language I can think of off the top of my head. It's a reference to a variable in lexical scope.

What python does slightly differently is writing to variables in outer scopes. But it still closes over references.

discuss

order

Jach|14 years ago

The writing to variables in outer scopes is what I meant by a lack of actual name-binding, due to the way Python does assignments; it seems I expressed that poorly. Here's a better attempt. The top poster's example simply doesn't work in Python:

    >>> i = 0
    >>> def inc():
    ...   i += 1
    ...
    >>> print i
    0
    >>> inc()
    Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "<stdin>", line 2, in inc
    UnboundLocalError: local variable 'i' referenced before assignment
So variables are name-bound in the sense that you can read from their original name and reference but you can't assign in normal ways. (Python has closures, which I said, just not typical closures that other languages might have.) Leading to the pattern of wrapping an array or dict or class around the thing you're interested in.

    >>> i_wrapped = [0]
    >>> def inc():
    ...   i_wrapped[0] += 1
    ... 
    >>> print i_wrapped[0]
    0
    >>> inc()
    >>> print i_wrapped[0]
    1
One could argue that one shouldn't really have such mutable state inside a closure of the enclosed items, which I do, but a person expecting to (set!) or the like is going to be surprised.

Edit: I guess it should be said that Python 3 has the 'nonlocal' keyword, and Python 2 has the 'global' keyword for global cases, which allows for expected behavior. So the functionality is still there, but still needs an extra statement.

    >>> i = 0
    >>> def out():
    ...   i = 0
    ...   def inc():
    ...     nonlocal i
    ...     i += 1
    ...   print(i)
    ...   inc()
    ...   print(i)
    ... 
    >>> print(i)
    0
    >>> out()
    0
    1
    >>> print(i)
    0

enneff|14 years ago

Python is a bad example here, as its scoping rules are inconsistent and frequently surprising.