On 12 Apr 2005 08:00:42 -0700, "Michele Simionato" <[EMAIL PROTECTED]> 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) > Thanks, that is nice and simple, though caching instances of a class according to initialization parameters is not quite the same concept as singleton instances, I think. OTOH, if you want to pass differing parameters to the same instance of a class, there are lots of methods (pun ;-) to do that that are clearer than (ab)using the constructor interface. I.e., what is the difference between shared access to a callable instance in a module vs shared access to a strange class in the same place? Hm, just had a thought re memoize: you could give it its own optional hashing function as a keyword argument, and let it use that as a key for memoize_dic. Then you could use that to make a singleton(-making) class or a dual/doubleton-making class like bool, e.g., Bool below ----< memoize.py >-------------------------------------------------------- def memoize(arghash=lambda args:args, method=False): def _memoize(func): memoize_dic = {} def wrapped_func(*args): key = arghash(args[method:]) if key in memoize_dic: return memoize_dic[key] else: result = func(*args) memoize_dic[key] = result return result wrapped_func.__name__ = func.__name__ wrapped_func.__doc__ = func.__doc__ wrapped_func.__dict__ = func.__dict__ return wrapped_func return _memoize def mkPolyton(arghash=lambda args:args): class Memoize(type): # Singleton is a special case of Memoize @memoize(arghash, True) # (with arghash=lambda args:0 -> singleton) def __call__(cls, *args): return super(Memoize, cls).__call__(*args) return Memoize class Bool(int): __metaclass__ = mkPolyton(lambda args:args and args[0] and 1 or 0) def __repr__(self): return ('False', 'True')[self] __str__ = __repr__ def tests(todo): if '1' in todo: @memoize() def square(x): return x*x print '[id(square(1234))...]: ten have same id:', [id(square(1234)) for x in xrange(10)].count(id(square(1234))) == 10 if '2' in todo: F = Bool(0) # init cache with proper False value T = Bool(1) # ditto for True value print 'T:', T, id(T) print 'F:', F, id(F) print '[id(Bool(1..10))...]: ten have same id:', [id(Bool(x)) for x in xrange(1,11)].count(id(T)) == 10 if __name__ == '__main__': import sys tests(sys.argv[1:]) -------------------------------------------------------------------------- Result (not exactly a thorough test ;-): [16:36] C:\pywk\ut>py24 memoize.py 1 2 [id(square(1234))...]: ten have same id: True T: True 49271436 F: False 49271884 [id(Bool(1..10))...]: ten have same id: True BTW, I found this page interesting: http://c2.com/cgi/wiki?SingletonPattern Regards, Bengt Richter -- http://mail.python.org/mailman/listinfo/python-list