Singleton-like pattern
Pedro Werneck
pedro.werneck at bol.com.br
Fri Aug 1 22:25:27 EDT 2003
On 1 Aug 2003, Bengt Richter wrote:
> >> class MultiSingleton(type):
> class MultiSingleton(object):
> >> def __call__(cls, *args, **kwds):
> def __new__(cls, *args, **kwds):
> >> cache = cls.__dict__.get('__cache__')
> >> if cache is None:
> >> cls.__cache__ = cache = {}
> >> tag = str(args) + str(kwds)
> tag = '%r%r'% (args, kwds) # might be an alternative
> >> if tag in cache:
> >> return cache[tag]
> >> obj = object.__new__(cls)
> >> obj.__init__(*args, **kwds)
> >> cache[tag] = obj
> >> return obj
This is exactly what I did at first... I only changed it to a metaclass
because I was adding it to a module that already contain some other
metaclasses I use; I think it's more elegant as I said before... a
'quick and dirty' benchmark with the timeit module returned the
folowing results, and in this project I will be dealing with a database
of 7000+ items, this 20% bit may help a little:
__metaclass__:
[39.744094967842102, 40.455733060836792, 42.027853965759277]
__new__:
[47.914013981819153, 48.721022009849548, 49.430392026901245]
On 1 Aug 2003, Michele Simionato wrote:
> "memoize" is a possible name for this. Notice that the metaclass is a
> bit of overkill, you may well use a simple function for this job.
Hey... you wrote such a good article on python metaclasses and now don't
want people to use them ? :)
> Does (args,kw) work in general? IWT you could easily get something unhashable?
> IWT using a tuple of actual args may also be a bad idea since it would prevent callers'
> temp args from being garbage collected. I use repr to avoid that, maybe mistakenly?
> About the issue of finding a suitable key, in the same situation I have
> used the tuple (args,kw) as key. But me too I would like to ask if this is a
> good idea. What's the custom solution for getting a good key from
> a dictionary ?
Actually, (args, kw) doesn't work at all, even if you only get hashable
arguments... the 'kw' dict invalidate it as a key... besides, there's the
garbage collection problem, as Bengt Richter mentioned...
The "%r%r"%(args, kwds) works, as well as str((args, kwds))), but it
breaks if you get as argument an object with the default __repr__, as
the object id may be different, even if they are equal. Overriding __repr__
and returning a real representation avoids this problem.
Thanks for your time.
Pedro Werneck
More information about the Python-list
mailing list