Welcome, guest | Sign In | My Account | Store | Cart

Allows decorating and caching expensive data consuming tasks

Python, 31 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class CachedSingleton(object):
    """Provides caching singleton storage for data access decoration.
    Usage:
        class CachedSingletonClass(CachedSingleton):
            def _getitem(self, name):
                # implement data getting routine, such as db access
        
        CachedSingletonClass().attribute1 # returns value as if _getitem('attribute1') was called  
        CachedSingletonClass().attribute2 # returns value as if _getitem('attribute2') was called  
        CachedSingletonClass().__doc__ # returns real docstring  
    """    
    __instance = None
    
    def __new__(classtype, *args, **kwargs):
        if classtype != type(classtype.__instance):
            classtype.__instance = object.__new__(classtype, *args, **kwargs)
            classtype.__instance.cache = {}    
        
        return classtype.__instance
       
    # to be implemented by contract in the descendant classes
    def _getitem(self, name):
        return None
        
    def __getattribute__(self, name):
        try:
            return object.__getattribute__(self, name)
        except:
            if not self.cache.has_key(name):
                self.cache[name] = self._getitem(name)
            return self.cache[name]

3 comments

Alexander Artemenko 15 years, 4 months ago  # | flag

I think, that this is the shorter and faster implementation:

class CachedSingleton(object):
    """Provides caching singleton storage for data access decoration.
    Usage:
        class CachedSingletonClass(CachedSingleton):
            def _getitem(self, name):
                # implement data getting routine, such as db access

        CachedSingletonClass().attribute1 # returns value as if _getitem('attribute1') was called··
        CachedSingletonClass().attribute2 # returns value as if _getitem('attribute2') was called··
        CachedSingletonClass().__doc__ # returns real docstring··
    """
    __instance = {}

    def __init__(self):
        self.__dict__ = self.__instance

    def _getitem(self, name):
        'to be implemented by contract in the descendant classes'
        return None

    def __getattr__(self, name):
        value = self._getitem(name)
        setattr(self, name, value)
        return value
David Lambert 15 years, 4 months ago  # | flag

Rather than returning None, I'd have CachedSingleton._getitem

    raise Exception(NotImplemented)
Eugene Mirotin (author) 15 years, 3 months ago  # | flag

Alexander, your solution does not solve 2 problems: 1) caching, as you call the _getitem every time 2) accessing existing attributes of the object (like __doc__) instead of calling _getitem for them

David, thanks, raise is much more pythonic in this case

Created by Eugene Mirotin on Wed, 26 Nov 2008 (MIT)
Python recipes (4591)
Eugene Mirotin's recipes (1)

Required Modules

  • (none specified)

Other Information and Tasks