Need help with Python scoping rules

Miles Kaufmann milesck at umich.edu
Thu Aug 27 13:27:40 EDT 2009


On Aug 26, 2009, at 1:11 PM, kj wrote:
> I think I understand the answers well enough.  What I *really*
> don't understand is why this particular "feature" of Python (i.e.
> that functions defined within a class statement are forbidden from
> "seeing" other identifiers defined within the class statement) is
> generally considered to be perfectly OK.  IMO it's a bizarre,
> inexplicable blindspot (which, among other things, gives rise to
> a certain worry about what other similar craziness lurks under
> Python's image of rationality).  I have never seen even a half-hearted
> justification, from a language design point of view, for why this
> particular "feature" is worth having.

Guido's design justifications:
http://mail.python.org/pipermail/python-dev/2000-November/010598.html

--

My personal justification:

Python has used the same basic method of class creation since the very  
beginning: create a new local namespace, execute the class suite in  
that namespace, and then create a class, using the contents of the  
namespace as the class attributes.  The important thing to note here  
is that there are really *two* namespaces--the local namespace that  
exists while the class suite is being executed (what I call the "suite  
namespace"), and the namespace of the class itself--and the first  
ceases to exist when the second is created.  The two namespaces  
generally contain the same names at the point that the transfer  
occurs, but they don't have to; the metaclass (which constructs the  
class) is free to mess with the dictionary of attributes before  
creating the class.

Suppose for a moment that the suite namespace *were* visible to nested  
scopes.  The simplest and most consistent implementation would be to  
have a closure generated by a class statement be similar to that  
generated by a function--i.e., the closure would be over the suite  
namespace.  This hardly seems desirable, though, because the suite  
namespace and the class namespace would get out of sync when different  
objects were assigned to the class namespace:

class C:
   x = 1
   def foo(self):
       print x
       print self.x

 >>> o = C()
 >>> o.foo()
1
1
 >>> o.x = 2
 >>> o.foo()
1
2

Surely such an implementation would be considered an even larger  
Python wart then not having the suite namespace visible to nested  
scopes at all.  But it's better than the alternative of trying to  
unify the class suite namespace and the class namespace, which would  
be a nightmare of special cases (adding/deleting class attributes?  
descriptors? __getattr__?) and require an implementation completely  
separate from that of normal nested scopes.

-Miles

P.S. Just for fun:

import types

def make_class(*bases):
"""Decorator to allow you to (ab)use a function as a class definition.

The function must take no arguments and end with 'return locals()';
bases are (optionally) specified as arguments to make_class;
metaclasses other than 'type' are not supported.

 >>> @make_class
... def C():
...     greeting = 'Hello'
...     target = 'world'
...     def greet(self):
...         print '%s, %s' % (self.greeting, target)
...     return locals()
...
 >>> C().greet()
Hello, world
"""

def decorator(func):
   return type(func.func_name, bases, func())
if len(bases) == 1 and isinstance(bases[0], types.FunctionType):
   func = bases[0]
   bases = (object,)
   return decorator(func)
if not bases:
   bases = (object,)
return decorator




More information about the Python-list mailing list