Namespace hack

Steven D'Aprano steve+comp.lang.python at pearwood.info
Thu May 24 04:50:59 EDT 2012


>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



More information about the Python-list mailing list