Borg vs Singleton vs OddClass

Carl Banks pavlovevidence at gmail.com
Sun Sep 28 05:29:07 EDT 2008


On Sep 27, 2:12 pm, Lie <Lie.1... at gmail.com> wrote:
> I'm thinking about this design pattern (I don't know if anyone has
> ever thought of this pattern before):
>
> class OddClass(object):
>     def __init__(self):
>         global OddClass
>         OddClass = self
>     def __call__():
>         return self
>
> The OddClass is a class that would overwrite its own class definition
> at its first instantiation. OddClass defines __call__ so that
> subsequent "instantiation" (technically it is no more an
> instantiation, but Duck Typing says it does) of the class would return
> the single instance.
>
> It do have a problem though, that you can't do isinstance(a, OddClass)
> since the name OddClass no longer refers to the OddClass class
> descriptor, but to an instance of OddClass.

I recommend against your idiom above.  The main issue I have about it
is that it rebinds the symbol implicitly, which is almost always a bad
idea.  What if a user does something like "from oddclassmodule import
OddClass"?  Then the user will get a new instance every call since it
never rebinds the imported symbol.

Just don't do it this way.

You could rewrite it like this to avoid the implicit rebinding, and to
take care of the isinstance issue as well:

class NotSoOddClass(object):
    def __new__(cls):
        self = getattr(cls,"_instance",None)
        if self is None:
             self = cls._instance = object.__new__(cls)
        return self


Or you could just use a lazy factory function like this, where the
user is only supposed to use Factory and not create the class
directly:

class _NotOddClass(object):
    # nothing odd

def Factory():
    obj = getattr(_NotOddClass,"_instance",None)
    if obj is None:
        obj = _NotOddClass._instance = NotOddClass()
    return obj


If you're real kinky you can use a metaclass.  There are reasons to
prefer any of these.  I'd recommend the factory function unless you
think the users could significantly benefit from type inspection.

Just don't do it by rebinding the class name.  That's not nice.


Carl Banks



More information about the Python-list mailing list