Five Easy Pieces: Simple Python Non-Patterns

Alex Martelli, AB Strakt

Abstract

The concept of Design Patterns (and full fledged Pattern Languages) has rapidly become deservedly popular. Sometimes, however, one is addressing issues that are too simple to really need the power of these semi-formal approaches. When this is the case, focusing on such powerful approaches may be overkill, somewhat similar to the "Big Design Up Front" fallacy so prevalent in software development. Python has a knack for making many issues simpler. This, in turn, enables use of simpler conceptual tools, such as an idiom in lieu of a Design Pattern. Sometimes, indeed, it's enough to just follow "good common practice". Simplicity is an excellent quality to strive for. This paper argues for this perspective, and exemplifies it with five simple Python "solution elements" that are not Design Patterns but may, to some extent, be satisfactorily substituted for DP's in various contexts.

Patterns and non-Patterns

"Design Patterns" (henceforth DP), which had been brewing for quite a while, became suddenly and deservedly popular in the software development community when E. Gamma, R. Helm, R. Johnson, J. Vlissides (henceforth the "Gang of Four", or Gof4) published their book "Design Patterns" in 1995. The wide Patterns community has produced a lot of other fascinating publications connected with software development, particularly on Pattern Languages (integrated, coordinated systems of Patterns) in every conceivable area, from organizational structure, to analysis, to development processes, as well as in the design field. Although a complete collection of all fundamental books and articles on these themes would overflow the average developer's available shelf space, any developer should at least be familiar with the original Gof4's DP book, M. Fowler's "Analysys Patterns" and "Refactoring", Vlissides' "Hatching Patterns" (all very practical, highly usable books, directly oriented to software development), and some wider-view philosophical reflection work (my personal "dark horse" suggestion for the latter category, focusing on Alexander's original work on Pattern Languages for building architecture, is N. Salingaros' The Structure of Pattern Languages).

But I come neither to praise Design Patterns, nor, most particularly, to bury them: just to offer a small alternate perspective of their use, and non-use, when one is developing Pyhon programs.

I focus on contrast (or, actually, just nuance!) from the Gof4's DP book, for definiteness and because (by its superb quality, and for being in the right place at the right time) it's the best known DP book in the software development community. The Gof4 do make the point, right in the first chapter, that "the choice of programming language is important because it influences one's point of view", and that in fact what is or isn't "worthy" of being framed as a DP (or even feasible to so frame) is language dependent. Many of their patterns are of course C++ specific, at least to the extent of making most sense in a C++ context (compile-time type checking, etc).

More to the point, however, a DP (and, even more, a complete Pattern Language) is a conceptually "heavy weight" construct. Setting down a DP requires a semi-formal approach: identifying relevant object and classes, at the right levels of abstraction; then singling out and articulating intent, motivation, applicability, structure, participants, collaboration, consequences, implementation; most particularly, researching, finding, and documenting Known Uses. Known Uses are not an optional element of a DP: at the very least (i.e., by the Gof4's relatively benign criterion), it's not a pattern unless you can identify at least two usage examples from different domains. Developing the DP itself implies a substantial investment of effort, so the "known uses" are needed to provide some assurance that the whole conceptual edifice is indeed worthy of that effort, having proven itself in the field. This is just fine and dandy when this considerable overall investment of time and energy pays back by helping us control and conquer complexity, which is often the case. But what if some of the complexity goes away, or at least is considerably diminished, by the programming language we're using?

Python's forte is simplicity. Again and again, problems that are difficult in other languages scale down to "pretty easy" in the light of Python's bright Sun. The amount and caliber of intellectual weaponry that it makes sense to bring to bear on a problem depends on the problem's difficulty level. For a simpler problem, an informal approach may make more sense, while a harder problem might profit from more structured and formalized procedures. One plus of making problems simpler is that, the simpler a problem, the more simplicity you can deploy in solving it. Of course, one always aims (or should) at making each solution as simple as it can possibly be (but, admittedly, no simpler than that:-). Maybe you can get away with an idiom (language specific usage), or even just "good common practice", where another language would require you to unearth and apply a full-fledged design pattern. At times, it's a reasonably big win, in terms of simplicity, even just to avoid forcing an aspect of the solution into the object oriented mold (so pervasive, and indeed so often appropriate, in software development Design Patterns). One aspect of Python's simplicity is, indeed, that you only do OO when you want to!

Borg versus Singleton

A popular, widely implemented Gof4 design pattern is Singleton. One can't help but wonder why: besides the catchy name, what does Singleton offer, that makes it so appealing? The DP's stated Intent is to "ensure a class only has one instance" (and provide a global point of access to it). But why would we want to ensure that? Aren't we entering in the middle of the action, where a specific approach has already been chosen to solve some other actual underlying problem, just as in Bentley's classic "How do I use the system sort from within my program" question (in the very first essay of his outstanding "Programming Pearls")?

I think we are. Coming to the Motivation, in fact, we find that "It's important for some classes to have exactly one instance. Although there can be many printers in a system, there should be only one printer spooler". And so (maybe) there should be, depending on the system that we're modeling. But this still doesn't tell us why that "one printer spooler" (in the system we're modeling) should necessarily (or optimally) be the "exactly one instance" of some specific class (in the software we write to model that system)!

There appears to be a lot of unspoken subtext in this intent and motivation. It is taken for granted, I surmise, that instance identity must (or, at least, had better be) in one to one corresponence with an "entity in the real world" (or, more precisely, a conceptual entity in the worldview that our software system is modeling). Some schools of OO design take this as a given, but the Gof4 argue directly against this earlier on in the book (in 1.6: "object oriented designs often end up with classes that have no counterpart in the real world ... abstractions that emerge during design are key to making a design flexible"). Right on! I happen to agree very closely with this opinion. Yet, in identifying Singleton's intent and motivation, the need for "counterparts" seems to be an unspoken assumption.

Object identity is a frail reed on which to rely. A. Korzybski, engineer extraordinaire, had choice words on the subject of "the is of identity" (an expression he credits to mathematician W. S. Jevons), but G. Santayana had already remarked that "Whenever I use the word 'is', except in sheer tautology, I deeply misuse it", and L. von Wittgenstein, another contemporary engineer of notice, had similarly (but, characteristically, more analytically and verbosely) observed "to say of two things that they are identical is nonsense, and to say of one thing that it is identical with itself is to say nothing at all". Back to Korzybski, his best known quote might as well be directly on the issue of the need for "counterparts in the real world" of objects in an OO design: "the map is not the territory"!

What's in an instance

Lest I be accused of escaping into philosophy (but I am quoting mostly engineers!), let's look closer at that "instance" thingy (of which Singleton wants to ensure a certain class has only one). In Python, an instance has an identity: we know because we can print id(instance) and see that identity displayed as an integer number right in front of our eyes. An instance has state: assuming the instance belongs to a "classic class" (an assumption that we'll have to critically revisit later, of course), the instance's state (sticking for the moment to its "direct", per instance part) is entirely held in instance.__dict__. An instance has behavior, coded in its methods (which, in most cases, come [some have argued, should always come] as the methods of instance.__class__ -- some of them, of course, could in turn be inherited, but that's neither here nor there). That's it.

Of course, an instance's "state" in a wider sense may partly come from elsewhere -- instance.__class__.__dict__ is a popular place in which to keep some state (that part which is shared by all instances of the class), and then there are global variables in sys.modules[instance.__class__.__module__] .__dict__, and, potentially, even more indirect state containers. But, as we're discussing Singleton, we need not dwell on all of these sources, which are obviously and implicitly held in common by all instances of a class (and possibly by other entities yet). If there is any motivation for ensuring that a class is only ever instantiated once, it cannot lie in aspects in which other instances of the same class, if they existed, would be identical and indistinguishable; the hypothetical motivation we're looking for has to rest, if anywhere, then in those aspects which might distinguish, i.e., differentiate, a multiplicity of instances, were they allowed.

By the same token, the hypothetical advantage of Singleton cannot be about behavior (code). Normally, all instances of the same class share behavior. We can arrange for deviations from this rule, by binding freshly created bound methods as part of per instance state, but it's quite a moot point whether we ever should. Again, therefore, behavior-wise it cannot matter much whether we constrain a class to just one instance: even if the class had several instances, they'd share behavior, as long as we conventionally agree to eschew the dubious practice of creating and binding new per instance bound methods, at least regarding instances of that particular class. (Let's not forget that Python gains much of its ease and simplicity by substituting clear, sensible conventions in place of the hard, strictly-enforced rules which many other languages try to impose on programmers...).

So, it boils down to identity, and (per instance) state. Why would we need to ensure singleness of identity? If it's for the purpose of testing equality with is, why not define __equal__ instead -- that gives us at least as much control. If it's for the purpose of using the instance as a dictionary key, without forcing the instance to be immutable, we can get there just as well by defining __hash__ -- the "immutability" only needs to refer to equality comparison status being unchangeable, and hash(instance) similarly fixed. We don't need to get metaphysical about this, but, should we want to, it's easy to argue that "immutability" is defined by the context: if we ensure that the dictionary code, the only relevant "observer", can never notice a mutation, then who's to say any mutation has in fact occurred...? So, naah, we don't really care about identity, not deeply at all. So, is it all about per instance state...?

I think it is. When we say there's only one printer spooler, all we really care about is that there be only one "printer spooler state" -- just one set of queues, jobs in the queues, currently set options, and so forth. Now this is concrete and juicy enough to sink our teeth into. Don't we need to ensure there is only one instance of the class, so that there will only be one "occurrence" of the relevant state?

Borg: just share state!

And the answer is, no, of course we don't. Not in any language, or object model, actually. As long as we arrange all instances, whatever number thereof might be in existence, to share their state (typically by delegation in some form), we satisfy the real application need that may indeed arise -- uniqueness of state. Ensuring that the "number of instances" is identically equal to 1 is one approach, but it's far from the only one!

So we need to weigh the actual advantages and disadvantages of the Singleton approach versus delegation based alternatives. In the alternatives, we allow client code to instantiate the target class freely, but we must arrange for all instances thus created to delegate their state to a single agent. You could look at these alternatives as Structural (or even, by a bit of a stretch, Behavioral!) patterns, while Singleton is a Creational pattern. For example, it's easy to envision the connection (almost antisymmetric) between the shared-state multiple instances, and DP Flyweight -- some of the Applicability issues (state is made extrinsic, the application must not depend on object identity) are very close.

Before we proceed further, we really need a catchy name. Singleton thrives, "out there" in the real world of software development, in good part because its name is so catchy. Now what name would well represent these sort-of-Flyweight objects, numerous as to identity, but deeper down all the same, indistinguishable, because they all share state? Well, what about Borg? After all, the several instances (with distinct identity) are really all One because they have no distinct state. Identity is irrelevant, resistance is futile, prepare to be assimilated...! Yep, it works (and I am indebted to D. Ascher for suggesting this name in discussion on the Python Cookbook site).

So, how hard is it to implement Borg? Not very, in any language or object model I know of -- at worst, one has to explicitly code delegation, but it's generally not even as bad as that. For example, in Consequences n.5 of Singleton, the Gof4 claim Singleton is "More flexible than class operations" (use of static member functions in C++), for example because those can't be overridable (virtual, in C++ terms). True, but so what? Who'd ever want to use class (static) methods? All we need is for the instance methods (which can perfectly well be virtual ones in C++) to only use "static" (per class, not per instance) member data -- prepend a "static" to all data members, leave the methods per instance (virtual if you need or want them that way), bingo, instant C++ Borg.

Borg in Python

But, of course, it is even easier in Python (isn't it always?):

class Borg:
    _shared_state = {}
    def __init__(self):
        self.__dict__ = self._shared_state
Voila: derive your application class from Borg (mixin like), remember of course to invoke Borg.__init__(self) right at the start of your own __init__ if any, and your class is a Borg -- all of its instances share state. Your own class may in turn override Borg's _shared_state class attribute (which is why we access the attribute through self, not directly by qualifying Borg -- and also, of course, why the attribute's name is best coded with one leading underscore, not two:-) depending on whether the subclass also wants to share states with other Borg classes -- you can easily arrange this in different ways (but, of course, resistance would be futile, so don't bother trying to arrange that).

Let's take a small step back to look at this tiny snippet of code with "beginners' eyes". Our design intent is for all instances to share state. Our Python knowledge tells us that each instance's state lives in the instance's __dict__ (ignoring without loss of generality other state that is already shared "by nature", and delaying for the moment the issue of Python 2.2's non-classic classes). Therefore, we explicitly express this design intent by just ensuring that the __dict__ is the same dictionary object for each and every instance, as elementarily done by our assignment. This is totally consequential, direct, even trivially obvious. I shamefully confess it took me a while (of fiddling with __getattr__, __setattr, and of course __delattr__, for example) before the obvious solution jumped right out at me. We can be so conditioned to complexity and cleverness, that it becomes hard to find the simplicity and obviousness "hiding" right in front of our nose! Fortunately, Python helps a lot in this quest for simplicity and clarity. So, back to examining what Borg is giving us...

Client code can just instantiate your Borg derived class, just as it might instantiate any other class. Borg is not a creational pattern (it verges more on the structural, although you could make a case about it having a behavioral aspect). Therefore, Borg carries no creational constraints, or, to put it another way, does not require creational Collaborations from client clode (like any other Python class meant to be inherited, it does of course require from subclasses the Collaboration of calling the superclass's __init__). If you want to have "controlled access to instances", for example (listed as benefit number 1 in the Gof4's Singleton pattern), deal with it in some other way, just as you would for any other class for which you deem controlled access desirable (a clearly orthogonal consideration from "limiting number of instances", or "state sharing": Borg is a simple idea, it doesn't conflate different and unrelated concerns).

Ability to subclass Singleton is very important in the Singleton DP: it's the second condition in Applicability, and the key issue in Consequences n.3 and n.5. However, the issue of choosing which of the Singleton's subclasses is actually instantiated looms large, taking up two thirds of the Implementation section and leading to a rich, complex solution (a registry of singletons). And this still doesn't meet many typical application needs. What if two separate subsystems each need to refine Singleton by subclassing? Instances of the two separate subclasses can't both exist, or else two separate "instances of Singleton" would exist, each as a subobject (base object) of one of them. Borg has no problem with this: as many instances as needed exist, all sharing state, and therefore in particular the Borg subclass may be independently further subclassed as needed. Often, the independent subclasses are each providing different behavior tweaks or additions with different mixins. State will still be shared, but of course each independent subclass may easily avoid accidentally interfering with another in the usual way, i.e. by naming attributes and methods that are only needed for its internal operation with two leading underscores.

PolySingleton and PolyBorg

One claimed advantage of Singleton that Borg may not appear to match is Consequence n.4, "Permits a variable number of instances". When you're refactoring your code, you can of course easily de-Borgize a given application level class, but there's no easy third way: it's all or nothing -- either per instance state is shared, or it's kept by each instance on its own. On the other hand, a separate PolyBorg class isn't any harder to envisage, than the PolySingleton class the Gof4 may have had in mind when writing about this Consequence. Say, for example, that in the PolySingleton's case exactly 4 instances may exist, and each call to PolySingleton::Instance chooses which of the 4 instances to yield in round robin fashion, something like:

PolySingleton* PolySingleton::_instances[4];
int PolySingleton::_next=-1;

PolySingleton* PolySingleton::Instance() {
    ++_next;
    if(_next>=4) _next=0;
    if(_instances[_next]==0) {
        _instances[_next] = new PolySingleton;
    }
    return _instances[_next];
}
I'm not too sure this variation makes much sense, but perhaps there are cases in which it does, e.g. for load balancing (more often, I suspect a class with a limited number of instances would require some kind of selector argument for instance selection... it typically does matter which one of the separate instances you get... but that would make PolySingleton not interface compatible with Singleton any more!). But anyway, if this version of PolySingleton meets requirements, so does the following version of PolyBorg:
class PolyBorg:
    _shared_states = [{} for i in range(4)]
    _next = -1
    def __init__(self):
        self.__class__._next+=1
	if self.__class__._next>=4: self.__class__._next=0
	self.__dict__ = self._shared_states[self.__class__._next]
(we do of course have to be explicit about self.__class__.next, at least when we rebind it, to avoid it accidentally and uselessly becoming per instance -- it must stay per class).

Borg, and its variation PolyBorg, are the first two of our five easy non-Patterns. They are as easy as pie, mind you -- don't let the amount of discussion fool you into believing there's anything deep or difficult about them -- I was mostly addressing the complexity and hidden depths of Singleton (and PolySingleton). Look at the Python code again, it so much terser, clearer, and simpler than all of the discussion around it! Four lines of code for Borg, seven for PolyBorg, all clear and open and understandable at an elementary level. Python makes it so easy to unveil the simplicity that, without it, masquerades as complexity!-)

But aren't these Patterns...?

So, what makes Borg and PolyBorg non-patterns? Why, they miss the prime requisite -- Known Uses! That's right, folks, these are scary, dangerous, field-unproven, experimental ideas! Does this scare you off from the effort of studying and understanding them so you can apply them to everyday problems...? What effort? what study? they are clear at first sight to any Pythonista worth his or her salt. Indeed, they're so simple they may well have been independently reinvented over and over -- as is often the case in Python. It's so simple to just do it, that the effort of combing the literature and published sources looking for Patterns to extract is pretty hard to cost-justify -- sure, Python's readability and clarity reduces that cost, but it can't reduce it to the point of making it lower than the effort of writing four lines of code, or thereabouts!-). So, Borg and PolyBorg are not Patterns (with the uppercase-P:-) because they're too simple and elementary to justify a Pattern's necessary "infrastructure" investment, and particularly the research effort needed to find Known Uses -- and real Patterns do really need that infrastructure, and most particularly that research into Known Uses. Let's say Borg and PolyBorg are idioms, then, or, at best, lowercase-p patterns. Borg has first been proposed as a Recipe, and that may be as good a name as any for this class of Pythonic ideas!-).

RegisBorg and RegisFact

Going back to the requisite of "multiple instances, but in limited number", we might typically want each instance-request to have as an argument a desired-instance identifier, say a string. If an instance corresponding to the given identifier alreadt exists, that instance must be returned; otherwise, a new instance must be created and returned. This is getting pretty far away from the "just one instance" idea, and yet it is a reasonably frequent application need (think, for example, of opening files, or other URL's -- we may well want to ensure state is shared no matter how many times an URL is opened). Also, requirements akin to these are what the "registry of singletons" in the Gof4's Singleton DP Implementation section strongly suggest (at least, to me). Could Borg be stretched to accomodate this need -- an extensible registry of hive-minds, tagged by identifiers, with the right one available on demand...?

Well, yes, it's not all that different from PolyBorg after all, and of course Python's dictionaries make "the Registry" a snap:

class RegisBorg:
    _shared_states = {}
    def __init__(self, id):
        try: self.__dict__=self._shared_states[id]
	except KeyError: self.__dict__=self._shared_states[id]={}

It is a snap, but one must nevertheless question if it's the appropriate snap, or if we couldn't have snapped even more simply and fruitfully. After all, the amended specs sound more and more like a Creational request, and yet we're still using a solution that's rather Structural. Such a "category mismatch" should rightfully makes us a little bit uneasy. Aren't we over-stretching Borg, and abandoning the straight and narrow, but fruitful, path of simplicity, for a seductive but ultimately fraught one of cleverness and deviousness...? After all, the "intuitive" solution to the stated requirements,the one that comes to mind at once, would be an application of a Pattern (or pattern, or idiom, or Recipe...) "Factory with a Registry", or RegisFact for short:

class Whatever: pass
_instances = {}
def RegisFact(id):
    try: return _instances[id]
    except KeyError:
        _instances[id] = Whatever()
	return _instances[id]
RegisFact uses a Creational idea (a Factory, albeit, a trivially simple one -- just a function, how un-OO! -- rather than the powerful DP's such as Abstract Factory and Factory Method... so, here we have yet another non-Pattern, deliberately choosing simplicity over power) to implement something that feels very much like a Creational requirement. No "category mismatch", then, and surely, no cleverness, no deviousness.

But not really all that extra simplicity over RegisBorg, either, and substantially limited functionality. Abstract, semi-philosophical guidelines such as "no category mismatch" are often useful as broad rules of thumb, lighthouses helping us find our way in the fog. But it's even better when there is no fog around and we can just find our way by carefully examining our surroundings -- and Python's already-mentioned Sun is one good way to help fog disperse. Translation from too-fancy metaphors back down to Earth again: writing down some actual Python code, rather than reasoning in the abstract, we can more easily examine concrete perspectives of different possible solutions:-).

RegisBorg still has the same usefulness as the other Borg variations: we can subclass at will, to tweak behavior or add per-subclass state, while keeping the essential defining characteristic -- all instances (here, all instances with the same id) share state. Because of this, RegisBorg, exactly as above coded, already has usefulness, although class RegisBorg itself does just about nothing -- said class can handle the registry and state-sharing behavior, while subclasses provide application-specific, hopefully useful parts of behavior and state.

On the other hand, RegisFact, as coded, is not all that useful. Factory functions do not let client-code easily use inheritance, so, since class Whatever is hard-coded with certain behavior (as we wrote it, no behavior at all), that's the behavior (or lack thereof) that actually obtains from the point of view of RegisFact's clients. Better than nothing (we can still use the Whatever instances that factory function RegisFact yields as passive containers of arbitrary attributes... and maybe we've found one case where adding per-instance behavior is justifiable!-), but far from fully satisfactory.

Indeed, for most potential uses, RegisFact as written is too simple. Yes, there can be such a thing as an artefact that is too simple, not rich and complex enough, for the goals it should accomplish. RegisFact really wants to be quite a bit richer and more complex than it is, to deploy its full potential... Factories' speciality is their potential ability to return objects of different classes, according to specifics that the Factory can encapsulate. RegisFact could be extended to hold a registry of classes, and a set of rules (a Strategy Design Pattern might be very appropriate here!) to select the right class to instantiate for any given requested id -- parsing the id string, for example, and selecting accordingly. But it doesn't do any of that, as it stands... it just sort of sits there! So, RegisFact as written is "easy", yes, but... too easy -- neither fish nor fowl, neither as intrinsically simple as RegisBorg, nor as rich and sophisticated as the full-fledged Design Pattern it might one day become, RegisFact basically serves the purpose of convincing us that a thorough study of Design Patterns (and Pattern Languages) is anything but a waste of effort. Simplicity can (for a short while, until we examine it more closely, and check if it shines in the bright light, or starts getting soggy and melting) be somewhat illusory in its intuitive appeal!

Borg 2.2?

For completeness, and to reach the number of five non-patterns that justifies the neat title:-), let's examine how Borg plays with the "non-classic" classes introduced in Python 2.2. The "instant user appeal" of new classes is, first and foremost, that they can subclass built in types. However, they come with a whole panoplia of new possibilities and constraints. From the perspective of sharing state, in particular, the key issue that distinguishes a new-order class from a classic class is that the former doesn't keep all per instance data in a single dictionary. Rather, the class may define or inherit "slots", and part of all of per-instance state lives in the slots rather than in the dictionary. Moreover, even for classes whose instances do keep state in __dict__, the __dict__ attribute itself may not be assigned (rebound).

All in all, then, for a new-order class we cannot just "mix-in inherit" something like Borg and just have state be automatically shared, as for a classic class. So, we're back to the status quo as in most other languages, that is, Delegation. Again, that's definitely not a Design Pattern, but for a different reason: it's simply too fundamental, too basilar to good object-oriented design. It's not a DP for much the same reason integer addition, while loops, and subroutines aren't -- they are, rather, some of the fundamental building blocks out of which all designs (and the inherent patterns, or Patterns) are built and implemented. Gof4 single Delegation out among the fundamental principles they point out, right after polymorphism, mixin classes, "program to an interface, not an implementation" (Python translation thereof: don't typetest!-), and "favor object composition over class inheritance", and just before generics and the principles of "designing for change". All in Chapter 1, of course, before they start their Design Patterns catalog.

In Python, we're blessed with a particularly flexible and easy to code form of automatic Delegation, thanks to the fact that (for a classic class) every attribute (and methods are just attributes!) is looked up via method __getattr__ (and bound, re-bound, unbound via similar special methods, too, of course). In pre-2.2 Python, we mostly used automatic Delegation to "inherit from built-in types" -- we couldn't inherit, but we almost didn't notice (except where some uncouth piece of framework or client-code typetested, and thus broke the wonderful, smooth polymorphism...!) -- reprising Gof4 again, "Delegation ... shows ... you can always replace inheritance with object composition" (unless somebody's busy coding deuced typetests, of course). In Python 2.2, we mostly don't need automatic Delegation for that, but it's anything but obsolete -- it still plays a precious role when we need to "dress up" anything that's not a classic class as if it were a classic class, to exploit the regularity and simplicity of "all per instance state is in __dict__" and similar wonderful simple rules (that don't generalize to builtin types and non-classic classes). So, for example, "Borg 2.2" is actually:

class DeleBorg:
    delegate = None
    _shared_state = {}
    def __init__(self):
        self.__dict__=self._shared_state
    def __getattr__(self,name):
        return getattr(self.delegate,name)
    def __delattr__(self,name):
        return delattr(self.delegate,name)
    def __setattr__(self,name,value):
        return setattr(self.delegate,name,value)
with the caveat that somebody must set DeleBorg.delegate once, "from the outside", normally before the first time DeleBorg is instantiated. Of course, this non-Pattern is somewhat of a blueprint -- the structural (behavioral?) part to be mixed-in (not necessarily by multiple inheritance, for once) with some creational element (here masked by the convention of "external assignment to DeleBorg.delegate) -- the latter being (in this case) really indispensable to figure out what object (not of a classic class) DeleBorg is wrapping in a multiple (classic class) instances, shared-state facade. The facade is still worth having every time we want to be able, for example, to freely use subclassing for behavior tweaking without loss of the uniqueness-of-state defining characteristic.

So, it would seem, old non-Patterns (here, automatic Delegation) don't really ever die, they just fade away into somewhat more obscure corners of language usage...

References

[1]Big Design Up Front, http://xp.c2.com/BigDesignUpFront.html

[2]R. G. White, "Advantages and disadvantages of unique representation patterns", C++ Report 8-8 pp 28-25, Sep 1996

[3]E. Gamma, R. Helm, R. Johnson, J. Vlissides, "Design Patterns, Elements of Reusable Object-Oriented Software", Addison-Wesley 1995

[4]M. Fowler, "Analysis Patterns: Reusable Object Models", Addison-Wesley 1997

[5]M. Fowler, "Refactoring: Improving the Design of Existing Code", Addison-Wesley Longman 1999

[6]J. Vlissides, "Pattern Hatching: Design Patterns Applied", Addison-Wesley 1998

[7]C. Alexander, "The Timeless Way of Building", Oxford University Press 1979

[8]C. Alexander, et al, "A Pattern Language: Towns, Buildings, Construction", Oxford University Press 1977

[9]N. Salingaros, "The Structure of Pattern Languages", http://www.math.utsa.edu/sphere/salingar/StructurePattern.html"

[10]J. Bentley, "Programming Pearls, Second Edition", Addison-Wesley 2000

[11]A. Korzybski, "Science and Sanity: An Introduction to Non-Aristotelian Systems and General Semantics", Science Press 1933

[12]G. Santayana, "Skepticism and Animal Faith: Introduction to a System of Phylosophy", Dover 1923

[13]L. von Wittgenstein, "Logische-Philosophische Abhandlung", Annalen der Naturphilosophie 1922

[14]A. Martelli, "Singleton? We don't need no stinkin' singleton: the Borg design pattern", http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/66531

[15]A. Martelli, "Automatic delegation as an alternative to inheritance", http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52295