multi-Singleton-like using __new__

J Peyret jpeyret at gmail.com
Fri Feb 8 15:38:47 EST 2008


I think the metaclass stuff is a bit too black magic for a pretty
simple requirement.

Txs in any case for showing me the __init__ issue, I wasn't aware of
it.

Here's a workaround - not exactly elegant in terms of OO, with the
isInitialized flag, but it works.

>>> class RDFObject(object):
...     cache ={}
...     isInitialized = False
...     def __new__(cls,uri,*args,**kwds):
...         try:
...             return cls.cache[uri]
...         except KeyError:
...             print "cache miss"
...             res = cls.cache[uri] = object.__new__(cls)
...             return res
...     def __init__(self,uri):
...         if self.isInitialized:
...             return
...         print "__init__ for uri:%s" % (uri)
...         self.isInitialized = True
...
>>> r1 = RDFObject(1)
cache miss
__init__ for uri:1
>>> r1b = RDFObject(1)
>>> r2 = RDFObject(2)
cache miss
__init__ for uri:2
>>> r2b = RDFObject(2)
>>> print r2b
<__main__.RDFObject object at 0x87a9f8c>
>>>print r2
<__main__.RDFObject object at 0x87a9f8c>

Some things to keep in mind:

- Might as well give uri its place as a positional param.  Testing
len(*args) is hackish, IMHO.

- Same with using try/except KeyError instead of in cls.cache.
Has_key might be better if you insist on look-before-you-leap, because
'in cls.cache' probably expends to uri in cls.cache.keys(), which can
be rather bad for perfs if the cache is very big.  i.e. dict lookups
are faster than scanning long lists.

- I took out the threading stuff - dunno threading and I was curious
if that was causing __init__ twice.  It wasn't, again txs for showing
me something I dinna know.

- isInitialized is as class variable.  __init__ looks it up from the
class on new instances, but immediately rebinds it to the instance
when assigning self.isInitialized = True.  On an instance that gets re-
__init__-ed, self.isInitialized exists, so the lookup doesn't
propagate up to the class variable (which is still False).

Cheers




More information about the Python-list mailing list