Namespace hack



From the Zen of Python ("import this"):

Namespaces are one honking great idea -- let's do more of those!


Inspired by this, I have a decorator that abuses function closures to
create a namespace type with the following properties:

- all methods are static methods that do not take a "self" parameter;

- methods can see "class variables";

- external callers can see selected methods and attributes.


An example may make this clearer.

In a regular class:

class C:
x = 42
def spam(self, y):
return self.x + y
def ham(self, z):
return self.spam(z+1)


Notice that the class attribute x is visible to the outside caller, but
methods spam and ham cannot see it except by prefixing it with a
reference to "self".

Here's an example using my namespace hack example:

@namespace
def C(): # Abuse nested functions to make this work.
x = 42
def spam(y):
return x + y
def ham(z):
return spam(z+1)
return (spam, ham) # Need an explicit return to make methods visible.

However, class attribute x is not exposed. You may consider this a
feature, rather than a bug. To expose a class attribute, define it in the
outer function argument list:

@namespace
def C(x=42):
def spam(y):
return x + y
def ham(z):
return spam(z+1)
return (spam, ham)



And in use:

C.x
42
C.spam(100)
142
C.ham(999)
1042



Here's the namespace decorator:

import inspect

def namespace(func):
spec = inspect.getargspec(func)
ns = {'__doc__': func.__doc__}
for name, value in zip(spec.args, spec.defaults or ()):
ns[name] = value
function = type(lambda: None)
exported = func() or ()
try:
len(exported)
except TypeError:
exported = (exported,)
for obj in exported:
if isinstance(obj, function):
ns[obj.__name__] = staticmethod(obj)
else:
raise TypeError('bad export')
Namespace = type(func.__name__, (), ns)
return Namespace()


Have fun!


--
Steven
.



Relevant Pages

  • Partial Classes - Aspects
    ... Therefore I implemented some classes Term, Var, Number, Sum, ... def expand: ... will be copyied to the base class Term. ... functions do operate in the wrong global namespace. ...
    (comp.lang.python)
  • Re: Something in the function tutorial confused me.
    ... def f: ... create another place in the namespace of f ... You would instead interpret this similar Python code... ... f which refers to the integer object with the value 5. ...
    (comp.lang.python)
  • Re: func_code vs. string problem
    ... Since 'exec' is able to execute any string or bytecode in the current scope, it would seem possible to execute code of any function in any namespace. ... print abc self.test ... def test: print "ABC" def checkfunction: abc=10 exec myfunction.func_code def checkstring: abc=10 ...
    (comp.lang.python)
  • Re: closures and dynamic binding
    ... inner is located in the code -- where is is compiled. ... def f: ... instead maintains access to the namespace providing x. ... This is the dynamic aspect of closures: ...
    (comp.lang.python)
  • Re: Replacement for keyword global good idea? (e.g. modulescopeor module better?)
    ... >The specialness of globals and locals was part of Python's original simple ... >Accessing such names is already possible, even *after* the outer function ... >> def enclosing(): ... There is nowhere near the kind of control the programmer has over attribute namespace ...
    (comp.lang.python)