loop scope

Gonçalo Rodrigues op73418 at mail.telepac.pt
Mon Mar 15 09:14:33 EST 2004


On 15 Mar 2004 12:52:14 +0100, Jacek Generowicz
<jacek.generowicz at cern.ch> wrote:

>Jacek Generowicz <jacek.generowicz at cern.ch> writes:
>
>> Imagine (for the sake of brevity of argument --- I wouldn't dream of
>> suggesting such a "line-noise" syntax for Python) that you could use
>> "x := 3" to mean "create a new local binding for x", while "x = 3"
>> would mean "find the innermost x and rebind it", with function
>> parameters, loop variables, list comprehension variables all behaving
>> as if they were using ":=". Now you'll find that you gain a lot of
>> flexibility to do what is appropriate with scopes of variables used in
>> loops etc., and you have an opportunity to fix the immutability of
>> closures ...
>> 
>> (Of course there are "issues" ... what happens, for
>> example when you say
>> 
>>     def foo(a):
>>         a := 3
>>         a := 4
>> 
>> ... does that make three nested scopes for a?, is it an error?)
>
>Hmm, this is starting to intrigue me.
>
>What are the situations that need disambiguating?
>
>What situations do (or might) create inner scopes?
>
>"def" and "class" are currently the two ways of creating an inner
>scope (have I overlooked any others?) ... and we are considering the
>possibility of "for" doing the same (in two different flavours: loops
>and comprehensions).
>

Is it (entirely) correct to say that class opens a new scope? I don't
think so, since names bound within the class body become attributes of
the class object, they are not local variables -- you can reach them
from the outside.

>Current rules can be summarized as:
>
>  In a scope creating block (def, class), assignment introduces a
>  local binding, unless the name is declared global.
>
>It looks like what's missing (because originally there were no other
>scopes between local and global) is some way of declaring a name to
>refer to an enclosing scope which may or may not be the global scope.
>
>For example:
>
>  >>> def make():
>  ...     x = 0
>  ...     def show(): print x
>  ...     def inc(n): x = x+n
>  ...     return show,inc
>  ... 
>  >>> show,inc = make()
>  >>> show()
>  0
>  >>> inc(3)
>  Traceback (most recent call last):
>    File "<stdin>", line 1, in ?
>    File "<stdin>", line 4, in inc
>  UnboundLocalError: local variable 'x' referenced before assignment
>
>The problem is that the "x =" inside "def inc():" tells the compiler
>to treat "x" as local to the scope of "inc", and then the reference to
>"x" or the RHS of the same line refers to an unbound variable ("x" in
>the _local_ scope). "global" is there for exactly this sort of
>situation, except that it originates from a time when there were no
>nested scopes, so it offers no help if you want to refer to some scope
>other than the global or local.
>

There were discussions about this in in the python dev list. The only
proposal that stuck in my memory was an extension of the global
keyword where you had an option of specifying the scope, something
like:

def g(*args):

    x = None

    def f(*args):
        global x in g
  
The scope of a name is determined at compile time, so it seems
unavoidable that a declaration is needed. But I wished that there were
no declarations in Python and some OO form of treating scopes like
objects with the local names being its attributes were available --
but I am also well aware that this is a very idiosincratic preference
:-)

With my best regards,
G. Rodrigues



More information about the Python-list mailing list