Welcome, guest | Sign In | My Account | Store | Cart
from functools import wraps


def cached_class(klass):
   
"""Decorator to cache class instances by constructor arguments.
   
    We "
tuple-ize" the keyword arguments dictionary since
    dicts are mutable; keywords themselves are strings and
    so are always hashable, but if any arguments (keyword
    or positional) are non-hashable, that set of arguments
    is not cached.
    """

    cache
= {}
   
   
@wraps(klass, assigned=('__name__', '__module__'), updated=())
   
class _decorated(klass):
       
# The wraps decorator can't do this because __doc__
       
# isn't writable once the class is created
        __doc__
= klass.__doc__
       
def __new__(cls, *args, **kwds):
            key
= (cls,) + args + tuple(kwds.iteritems())
           
try:
                inst
= cache.get(key, None)
           
except TypeError:
               
# Can't cache this set of arguments
                inst
= key = None
           
if inst is None:
               
# Technically this is cheating, but it works,
               
# and takes care of initializing the instance
               
# (so we can override __init__ below safely);
               
# calling up to klass.__new__ would be the
               
# "official" way to create the instance, but
               
# that raises DeprecationWarning if there are
               
# args or kwds and klass does not override
               
# __new__ (which most classes don't), because
               
# object.__new__ takes no parameters (and in
               
# Python 3 the warning will become an error)
                inst
= klass(*args, **kwds)
               
# This makes isinstance and issubclass work
               
# properly
                inst
.__class__ = cls
               
if key is not None:
                    cache
[key] = inst
           
return inst
       
def __init__(self, *args, **kwds):
           
# This will be called every time __new__ is
           
# called, so we skip initializing here and do
           
# it only when the instance is created above
           
pass
   
   
return _decorated

Diff to Previous Revision

--- revision 4 2012-01-06 02:21:25
+++ revision 5 2012-01-06 02:24:08
@@ -18,7 +18,7 @@
         
# isn't writable once the class is created
         __doc__
= klass.__doc__
         
def __new__(cls, *args, **kwds):
-            key = args + tuple(kwds.iteritems())
+            key = (cls,) + args + tuple(kwds.iteritems())
             
try:
                 inst
= cache.get(key, None)
             
except TypeError:

History