singleton objects with decorators

Uwe Mayer merkosh at hadiko.de
Tue Apr 12 12:40:17 EDT 2005


Tuesday 12 April 2005 17:00 pm Michele Simionato wrote:

> I did not put memoize on __new__. I put it on the metaclass __call__.
> Here is my memoize:
> 
>  def memoize(func):
>      memoize_dic = {}
>      def wrapped_func(*args):
>          if args in memoize_dic:
>              return memoize_dic[args]
>          else:
>              result = func(*args)
>              memoize_dic[args] = result
>              return result
>      wrapped_func.__name__ = func.__name__
>      wrapped_func.__doc__ = func.__doc__
>      wrapped_func.__dict__ = func.__dict__
>      return wrapped_func
> 
>  class Memoize(type): # Singleton is a special case of Memoize
>      @memoize
>      def __call__(cls, *args):
>          return super(Memoize, cls).__call__(*args)

I tried it out and found the following "inconsistency":

>>> class Foobar(object):
...     __metaclass__ = Memoize
...     def __init__(self, *args): pass
...
>>> Foobar(1)
<__main__.Foobar object at 0x4006f7ec>
>>> Foobar(2)
<__main__.Foobar object at 0x4006f7cc>
>>> Foobar(3)
<__main__.Foobar object at 0x4006f82c>

Unless I'm using it incorrectly (I haven't done much metaclass programming
yet) this is the same problem was with using @memoize on __new__ and
__init__.

Talking so much about singletons I'm not even sure what the definition on
calling a singleton with different constructor parameter values is.

Anyways, a fix for that could be:

class SingletonFactory(type):
    single = {}
    def __call__(cls, *args):
        if (cls not in SingletonFactory.single):
            SingletonFactory.single[cls] = super(SingletonFactory,
cls).__call__(*args)
        return SingletonFactory.single[cls]


i.e. not caching the parameter values or types.

Uwe



More information about the Python-list mailing list