Namespaces are one honking great idea — let’s do more of those!
— The Zen of Python (PEP 20) by Tim Peters
In the quest for order and heirarchy in our code, namespaces are our chief weapon (along with fear and surprise). Namespaces come in 2 forms in python: Implicitly inside classes and functions, and explicitly as modules. Subtleties aside, modules are just namespaces with an odd usage: They must be files, and only other modules can parent them.
Of the implicit namespaces, each have their own “quirks”:
- Classes – these namespaces have two modes – “normal” and instanciated, and both have odd behaviours.
- Functions – their internal space cannot be accessed from the outside; they only provide locality.
All this babble was meant to demonstrate that these are not enough. You can’t always keep your code organized if your choice is only between file seperation, twisted behaviour or no-public policy.
What else could I possibly want?
Well, for example, dividing responsibilities inside a class. Classes infamously have several responsibilities, and while they all must reside inside the same class, there’s no reason why they should be blended inside each other.
Consider all of the GUI libraries you ever used. Now consider the following hypothetical GUI window:
class YetAnotherGuiWindow(whatever): ... namespace spatial: location = property(_get_loc, _set_loc) size = property(_get_size, _set_size) def move(self, where_to): ... namespace visual: color = property(_get_color, _set_color) ... ... #Somewhere Else guiwindow.spatial.move( guiwindow.spatial.pos + (5,5) ) guiwindow.visual.color = Colors.Black ...
Think how wonderful it would be to perform dir(guiwindow.visual) and see only visual possiblities, without all the other 500 attributes. Want to find an event? dir(guiwindow.events), it’s a rather short list. It would also be a lot clearer to the reader that when you try to access “background_process” you mean “threads.background_process” and not “cool_visual_filter_effects.background_process”.
There are more examples I could think of.
At this point I can foresee a possible response, that I wish to address in advance. People might propose that I rename methods to fake a namespace, and that the dir listing can work by filtering the names for that fake namespace. This would vaguely emulate what I’m hoping for, but I can’t help comparing it to writing C++ using C structs and function pointers.
I like your idea. Is there anything I can do with what python currently offers?
I have given this some thought. The short answer is: No. Python’s namespaces are crippled, and this cannot be solved. The long answer is: Maybe, depends on what you want. You could use a class to provide a namespace, in which all methods (perhaps through a decorator for each) would recieve the parent class’ instance as self, rather than their own. This is a bit tedious, as it requires addition to every function, so I tried to see if I can use python’s dynamic and introspective nature to my advantage:
def make_namespace(self, ns_cls): "This code iterates all functions in ns_cls and binds them to self" for attr_name in dir(ns_cls): attr = getattr(ns_cls,attr_name) if type(attr) == types.MethodType: setattr(ns_cls, attr_name, attr.__get__(self) )
Usage:
class YetAnotherGuiWindow: def __init__(self, pos, size, ...): ... self._size = size make_namespace(self, self.spatial) class spatial: ... def get_size(self): return self._size def set_size(self, size): self._size = size ... #Somewhere Else guiwindow.spatial.set_size( (100, 100) )
This seems to work fine for methods, but not for properties.
In fact, I couldn’t manage to write any code that would work for properties. Readers are welcome to see this as a challenge to produce such code. Honorable mentions promised to solvers.