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

Almann T. Goo almann.goo at gmail.com
Tue Feb 21 05:29:53 CET 2006


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 <http://www.python.org/peps/pep-0227.html>, 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<http://www.python.org/peps/pep-0020.html>).
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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://mail.python.org/pipermail/python-dev/attachments/20060220/6d910c2f/attachment.html 


More information about the Python-Dev mailing list