Namespace hack

Daniel Fetchinson fetchinson at googlemail.com
Thu May 24 09:04:34 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!

Funny, you got to the last line of "import this" but apparently
skipped the second line:

Explicit is better than implicit.

And you didn't even post your message on April 1 so no, I can't laugh
even though I'd like to.

Cheers,
Daniel


-- 
Psss, psss, put it down! - http://www.cafepress.com/putitdown



More information about the Python-list mailing list