[Python-Dev] PEP for Better Control of Nested Lexical Scopes

Bengt Richter bokr at oz.net
Tue Feb 21 15:29:11 CET 2006

On Tue, 21 Feb 2006 08:02:08 -0500, "Jeremy Hylton" <jeremy at alum.mit.edu> wrote:

>The lack of support for rebinding names in enclosing scopes is
>certainly a wart.  I think option one is a better fit for Python,
>because it more closely matches the existing naming semantics.  Namely
>that assignment in a block creates a new name unless a global
>statement indicates otherwise.  The revised rules would be that
>assignment creates a new name unless a global or XXX statement
>indicates otherwise.
>The names of naming statements are quite hard to get right, I fear.  I
>don't particularly like "use."  It's too generic.  (I don't
>particularly like "scope" for option 2, either, for similar reasons. 
>It doesn't indicate what kind of scope issue is being declared.)  The
>most specifc thing I can think of is "free" to indicate that the
>variable is free in the current scope.  It may be too specialized a
>term to be familiar to most people.
>I think free == global in the absence of other bindings.
Hey, only Guido is allowed to top-post. He said so ;-)

But to the topic, it just occurred to me that any outer scopes could be given names
(including global namespace, but that would have the name global by default, so
global.x would essentially mean what globals()['x'] means now, except it would
be a name error if x didn't pre-exist when accessed via namespace_name.name_in_space notation.

    namespace g_alias  # g_alias.x becomes alternate spelling of global.x
    def outer():
        namespace mezzanine
        a = 123
        print a  # => 123
        print mezzanine.a  # => 123 (the name space name is visible and functional locally)
        def inner():
            print mezzanine.a => 123
            mezznine.a =456
        print a # = 456
        global.x = re-binds global x, name error if not preexisting.

This would allow creating mezzanine like an attribute view of the slots in that local namespace,
as well as making namespace itself visible there, so the access to mezzanine would look like a read access to
an ordinary object named mezzanine that happened to have attribute slots matching outer's local name space.

Efficiency might make it desirable not to extend named namespaces with new names, function locals being
slotted in a fixed space tied into the frame (I think). But there are tricks I guess.
Anyway, I hadn't seen this idea before. Seems

Bengt Richter

>On 2/20/06, Almann T. Goo <almann.goo at gmail.com> wrote:
>> I am considering developing a PEP for enabling a mechanism to assign to free
>> variables in a closure (nested function).  My rationale is that with the
>> advent of PEP 227 , Python has proper nested lexical scopes, but can have
>> undesirable behavior (especially with new developers) when a user makes
>> wants to make an assignment to a free variable within a nested function.
>> Furthermore, after seeing numerous kludges to "solve" the problem with a
>> mutable object, like a list, as the free variable do not seem "Pythonic."  I
>> have also seen mention that the use of classes can mitigate this, but that
>> seems, IMHO, heavy handed in cases when an elegant solution using a closure
>> would suffice and be more appropriate--especially when Python already has
>> nested lexical scopes.
>>  I propose two possible approaches to solve this issue:
>>  1.  Adding a keyword such as "use" that would follow similar semantics as
>> "global" does today.  A nested scope could declare names with this keyword
>> to enable assignment to such names to change the closest parent's binding.
>> The semantic would be to keep the behavior we experience today but tell the
>> compiler/interpreter that a name declared with the "use" keyword would
>> explicitly use an enclosing scope.  I personally like this approach the most
>> since it would seem to be in keeping with the current way the language works
>> and would probably be the most backwards compatible.  The semantics for how
>> this interacts with the global scope would also need to be defined (should
>> "use" be equivalent to a global when no name exists all parent scopes, etc.)
>> def incgen( inc = 1 ) :
>>    a = 6
>>    def incrementer() :
>>      use a
>>      #use a, inc <-- list of names okay too
>>      a += inc
>>      return a
>>    return incrementer
>>  Of course, this approach suffers from a downside that every nested scope
>> that wanted to assign to a parent scope's name would need to have the "use"
>> keyword for those names--but one could argue that this is in keeping with
>> one of Python's philosophies that "Explicit is better than implicit" (PEP
>> 20).  This approach also has to deal with a user declaring a name with "
>> use" that is a named parameter--this would be a semantic error that could be
>> handled like "global " does today with a SyntaxError.
>>  2.  Adding a keyword such as "scope" that would behave similarly to
>> JavaScript's " var" keyword.  A name could be declared with such a keyword
>> optionally and all nested scopes would use the declaring scope's binding
>> when accessing or assigning to a particular name.  This approach has similar
>> benefits to my first approach, but is clearly more top-down than the first
>> approach.  Subsequent "scope" declarations would create a new binding at the
>> declaring scope for the declaring and child scopes to use.  This could
>> potentially be a gotcha for users expecting the binding semantics in place
>> today.  Also the scope keyword would have to be allowed to be used on
>> parameters to allow such parameter names to be used in a similar fashion in
>> a child scope.
>> def incgen( inc = 1 ) :
>>    #scope inc <-- allow scope declaration for bound parameters (not a big
>> fan of this)
>>    scope a = 6
>>    def incrementer() :
>>      a += inc
>>      return a
>>    return incrementer
>>  This approach would be similar to languages like JavaScript that allow for
>> explicit scope binding with the use of "var" or more static languages that
>> allow re-declaring names at lower scopes.  I am less in favor of this,
>> because I don't think it feels very "Pythonic".
>>  As a point of reference, some languages such as Ruby will only bind a new
>> name to a scope on assignment when an enclosing scope does not have the name
>> bound.  I do believe the Python name binding semantics have issues (for
>> which the "global" keyword was born), but I feel that the "fixing" the
>> Python semantic to a more "Ruby-like" one adds as many problems as it solves
>> since the "Ruby-like" one is just as implicit in nature.  Not to mention the
>> backwards compatibility impact is probably much larger.
>> I would like the community's opinion if there is enough out there that think
>> this would be a worthwile endevour--or if there is already an initiative
>> that I missed.  Please let me know your questions, comments.
>>  Best Regards,
>>  Almann
>> --
>> Almann T. Goo
>> almann.goo at gmail.com
>> _______________________________________________
>> Python-Dev mailing list
>> Python-Dev at python.org
>> http://mail.python.org/mailman/listinfo/python-dev
>> Unsubscribe:
>> http://mail.python.org/mailman/options/python-dev/jeremy%40alum.mit.edu
>Python-Dev mailing list
>Python-Dev at python.org
>Unsubscribe: http://mail.python.org/mailman/options/python-dev/python-python-dev%40m.gmane.org

More information about the Python-Dev mailing list