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

--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to