multi-Singleton-like using __new__
Arnaud Delobelle
arnodel at googlemail.com
Fri Feb 8 12:42:12 EST 2008
On Feb 8, 4:44 pm, Freek Dijkstra <fr... at macfreek.nl> wrote:
> Is there a best practice on how to override __new__?
>
> I have a base class, RDFObject, which is instantiated using a unique
> identifier (a URI in this case). If an object with a given identifier
> already exists, I want to return the existing object, otherwise, I
> want to create a new object and add this new object to a cache. I'm
> not sure if there is a name for such a creature, but I've seen the
> name MultiSingleton in the archive.
>
> This is not so hard; this can be done by overriding __new__(), as long
> as I use a lock in case I want my code to be multi-threading
> compatible.
>
> import threading
> threadlock = threading.Lock()
>
> class RDFObject(object):
> _cache = {} # class variable is shared among all RDFObject
> instances
> def __new__(cls, *args, **kargs):
> assert len(args) >= 1
> uri = args[0]
> if uri not in cls._cache:
> threadlock.acquire() # thread lock
> obj = object.__new__(cls)
> cls._cache[uri] = obj
> threadlock.release() # thread unlock.
> return cls._cache[uri]
> def __init__(self, uri):
> pass
> # ...
>
> However, I have the following problem:
> The __init__-method is called every time you call RDFObject().
You need to override the __call__ method of the metaclass. By default
is calls cls.__new__ then cls.__init__, e.g.:
class RDFObject(object):
# This metaclass prevents __init__ from being automatically called
# after __new__
class __metaclass__(type):
def __call__(cls, *args, **kwargs):
return cls.__new__(cls, *args, **kwargs)
# ...
HTH
--
Arnaud
More information about the Python-list
mailing list