Need help with Python scoping rules
milesck at umich.edu
Thu Aug 27 19:27:40 CEST 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:
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:
x = 1
>>> o = C()
>>> o.x = 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.
P.S. Just for fun:
"""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.
... def C():
... greeting = 'Hello'
... target = 'world'
... def greet(self):
... print '%s, %s' % (self.greeting, target)
... return locals()
return type(func.func_name, bases, func())
if len(bases) == 1 and isinstance(bases, types.FunctionType):
func = bases
bases = (object,)
if not bases:
bases = (object,)
More information about the Python-list