In the python execution model, a suite of code, when executed, has access to three namespaces - locals, globals and builtins - by which to convert names used in the suite into values to manipulate. Some of those values will be namespaces in their own right, enabling the suite to access those namespaces also. However, for the present I just want to discuss a suite's access to the the three namespaces accessible to it ab initio. These specify what python does when it meets a name not immediately preceded by a `.' (the latter, if it hasn't generated a parser error, is preceded by a specification of a namespace in which to look).
It took me a while to get used to the `two-namespace rule' (wherein we don't count the builtins because they're `hidden' and always there) but it grew on me. Yet another place where I pause to take a figurative hat off to Guido.
Python's execution model is described in terms of `code blocks' which correspond closely to the `suites' of the grammar. Each code block has a `local' namespace specific to itself; that of a function body gets a fresh local namespace each time it is called, which is forgotten when that call of the function pops off the stack; the code block of a module (and, likewise, of any class statements in the module's suite) gets executed once using the module (or class) object's namespace as its locals. Code in the block which modifies variables does so in the local namespace unless the name modified is the subject of a `global' statement in the block: all names modified in the block (whether or not the code involved gets executed in a particular run of the block) are local and will be read from the local namespace by any lookup during the block's execution.
A code block also has an associated `global' namespace: this is used for access to all non-local names and falls back on the built-in namespace (which is the namespace of the global's __builtins__). A module's global namespace coincides with its local namespace (so only gets used successfully (as globals) for lookup of builtins, which isn't done in local but is used as a fall-back in global); class and def statements have, as their globals, the globals of their context so, in practice, the global namespace of a piece of code is always the module in whose body the code appears (except for code being exec()ed and similar).
Now, when a function body gets executed, it seems right that its local namespace be discardable as soon as it returns. Likewise, when a build statement (which generalises class) has completed, its suite wrapper (in whose namespace the body of the build statement is executed) should also be discardable (though, of course, the newly built object isn't; and the builder used is at liberty to cause the wrapper to survive as, for example, the self seen as first parameter of methods on the built object). During execution of either a build suite or a function, one can define a new function: this may survive to be run after the given execution has completed, and must have access to its globals when run; so a def statement can't use, as its globals, the local namespace in which the def was executed. It is consequently forced to use the module namespace as its globals; for the suite of a def, Guido's choice is thus the only sensible one.
However, the body of a build (e.g. class) statement gets executed just once (for each object it builds) and this happens during execution of the code block which invokes the builder. Consequently, the build statement does have the option of using, as its globals, the namespace of, for instance, the function in whose body it appears. It could equally use the namespace of a class within whose body it is being defined, but it can refer to that by a name in the function or module which defines the class so will always prefer to use this outer namespace as globals.
This last is thus a case where something other than the current namespace rules could be used. For an example of where it would be useful consider
def out(key, val):
class dumb:
safe = val
def meth(self, _k=key): return _k, self.safe
return dumb
A class statement executed in the body of a module is visible in the module's namespace, hence visible to any code using that as its globals. A code block within the class statement, if it were to use the class' namespace as globals, would thereby lose access to the module's namespace and gain nothing useful into the bargain (since it could have accessed the class' namespace via the module): the same goes for class statements within class statements to arbitrary depth.
However, this fails for a class statement within a function: the body of the class statement (as it stands) cannot see the local namespace of the function at all, though the function can, after defining the class, transcribe such data into the class before returning. The class' suite can see, as its globals, the namespace of the containing module: this has its uses, too, but forces us to code the above as
def out(key, val):
class dumb:
def meth(self): return self.__class__._key, self.safe
dumb._key, dumb.safe = key, val
return dumb
using up a name (which can't even by __private) of the new class, dumb._key, as the means of tunnelling data from the function's namespace into the places I wanted it in the first version of this code.
Note that a function defined within a class statement (or other builder) will still have to use the module as its globals - it can't access the globals of the class statement when this is a function's locals, as this namespace would then have to survive until the newly defined function object is destroyed. We can still use the function's locals as globals for classes defined within classes in the body of the function, to arbitrary depth: but methods of these classes must use the module as their globals.
The class would lose access to the globals of the function, of course, but the function can transcribe things from its globals to its locals before embarking on the class statement. This parallels, in the present case, the need to transcribe things onto the class after its creation: compare and contrast. Suppose a method of my class wants to have access to some data known to the function which created the class. The present way is to store the value on the class and oblige the method to access it via self.__class__. The alternative will let me, for instance, pass it in as a hidden argument to the method - this avoids some clutter in the class' namespace, which I like. It will still let me store the value in the class' namespace and access it as before: and in this form the relevant code (in the class' body) just performs an ordinary assignment, e.g. `__name = val' reading val from globals and binding to local __name (which needn't be __private, but can be) whereas (at present), I'd have to say `newclass.name = val' (after the class' body) and wouldn't be able to use the class' magic namespace to store the value in.
So it might be worth changing the global namespace rules to:
use it as globals
use the surrounding globals
use that function's globals
use the surrounding code-block's globals
Equally, classify a code-block's use of a namespace as `ephemeral' if, like the locals of a function, the namespace will be discarded and forgotten once the code block has finished executing (though any __del__ behaviour it might be imagined to have would have to wait for garbage-collection to trigger it); otherwise, `persistent', meaning the effects of the code-block on the namespace are subsequently rememberable (notwithstanding how quickly the program might discard this memory). A newly created ephemeral wants a persistent namespace to use as its globals: if the globals of the context creating it are persistent, it uses those, otherwise it finds the ephemeral user of the namespace and uses their globals. A newly created persistent wants an ephemeral to use as its globals, so will use the locals of the context creating it if ephemeral: otherwise, it uses the creator context's globals.
During execution of the function, in its ephemeral namespace (used as locals), the module's namespace is used as global namespace. In python 1, at least, the module's namespace is also used as globals while executing the code which initialises a class (i.e. an object) in the body of the function. Consider the following:
stack = []
def example(datum, base, **data):
stack[:0] = [(datum, data)] # push
try:
class new (base):
datum = stack[0][0]
def __init__(self, bok = stack[0][1]):
self.data = bok
return new
finally: stack[:1] = [] # pop
During creation of the class to be returned, the top item of stack is used to provide values recorded, respectively, as an attribute of the class and as the default argument to a method of the class. This involved accessing example's arguments via globals: when these two statements are executed, the ephemeral name-space of example is `invisible'. Note, however, that `class new (base):' is executed in the function's namespace, so can see the name base to use its value as the one base of our new class: this doesn't have to go via stack.
Note that the transfer of datum could be achieved by assigning to new.datum after creation of new but before returning it. However, using data to initialise bok can't be dodged in any kindred way. Strictly, the above can't be relied on to work, at least not in a threaded interpreter where several threads might interweave executions of example.
Now, the byte-code compiled from the suite of a class isn't actually executed in the namespace of the class - in reality it's executed using an initially empty dictionary as namespace; that dictionary and the tuple of bases (if any, else the empty tuple) get used as the __dict__ and __bases__ of the new class, after the initialisation. However, if the class object were first created, then initialised by running its suite's byte-code in the new object's name-space, the code would be able to access the new class' __bases__ and __dict__ attributes, along (via inheritance) with all attributes inherited from bases. In such a case, we could do
def stretcher(datum, base, **data):
class dumb: pass
dumb.datum, dumb.data = datum, data
class new(dumb, base):
# inherit datum
def __init__(self, bok = __bases__[0].data):
# (one could even use `bok = data', implicitly
# accessing new.data, inherited from dumb.data)
self.data = bok
del dumb.data
return new
However, the namespace used in class initialisation can only see values created during that initialisation:
Python 1.5.2 (#5, Oct 4 1999, 13:36:16) [GCC 2.7.2.3] on linux2
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>> class dumb:
... one = 1
... two = one + one
...
>>> dumb.__dict__
{'one': 1, 'two': 2, '__doc__': None, '__module__': '__main__'}
>>> class test:
... row = __bases__
...
Traceback (innermost last):
File "", line 1, in ?
File "", line 2, in test
NameError: __bases__
>>> class test:
... bok = __dict__
...
Traceback (innermost last):
File "", line 1, in ?
File "", line 2, in test
NameError: __dict__
>>> class test(dumb):
... three = two + one
...
Traceback (innermost last):
File "", line 1, in ?
File "", line 2, in test
NameError: two
>>> class test:
... def __init__(self, __bok = 1):
... self.data = __bok
...
>>> test().data
Traceback (innermost last):
File "", line 1, in ?
File "", line 3, in __init__
NameError: _test__bok
(The last is a digression; note that `private' name munging doesn't happen for parameter names of def statements, but does in their suites. Arguably this is a bug: either it should happen for all names, or (which I like better) it should happen only for attribute references.) Still, the job can be done:
>>> def workable(datum, base, **data):
... class new(base): pass
... new.datum = datum
... def __init__(self, __bok = data):
... self.data = __bok
... new.__init__ = __init__
... return new
...
>>> new = workable(1, dumb, three=3)
>>> bob = new()
>>> bob.data
{'three': 3}
Written by Eddy.