ASPN ActiveState Programmer Network  
ActiveState, a division of Sophos
/ Home / Perl / PHP / Python / Tcl / XSLT /
/ Safari / My ASPN /
Cookbooks | Documentation | Mailing Lists | Modules | News Feeds | Products | User Groups
Submit Recipe
My Recipes

All Recipes
All Cookbooks


View by Category

Title: Sized Dictionary
Submitter: James Kassemi (other recipes)
Last Updated: 2006/07/02
Version no: 1.1
Category: Extending

 

Not Rated yet


Description:

Good demonstration of inheriting python default object types. Define a maximum size (items, not bytes) to limit to and use as a normal dictionary (be careful to have KeyError exception handling, or use the dictionary's get method with a default value).

Source: Text Source

import time

class SizedDict(dict):
    ''' Sized dictionary without timeout. '''

    def __init__(self, size=1000):
        dict.__init__(self)
        self._maxsize = size
        self._stack = []

    def __setitem__(self, name, value):
        if len(self._stack) >= self._maxsize:
            self.__delitem__(self._stack[0])
            del self._stack[0]
        self._stack.append(name)
        return dict.__setitem__(self, name, value)

    # Recommended but not required:
    def get(self, name, default=None, do_set=False):
        try:
            return self.__getitem__(name)
        except KeyError:
            if default is not None:
                if do_set:
                    self.__setitem__(name, default)
                return default
            else:
                raise

class CacheDict(dict):
    ''' A sized dictionary with a timeout (seconds) '''

    def __init__(self, size=1000, timeout=None):
        dict.__init__(self)
        self._maxsize = size
        self._stack = []
        self._timeout = timeout

    def __setitem__(self, name, value, timeout=None):
        if len(self._stack) >= self._maxsize:
            self.__delitem__(self._stack[0])
            del self._stack[0]
        if timeout is None:
            timeout = self._timeout
        if timeout is not None:
            timeout = time.time() + timeout
        self._stack.append(name)
        dict.__setitem__(self, name, (value, timeout))

    def get(self, name, default=None):
        try:
            focus = self.__getitem__(name)
            if focus[1] is not None:
                if focus[1] < time.time():
                    self.__delitem__(name)
                    self._stack.remove(name)
                    raise KeyError
            return focus[0]
        except KeyError:
            return default

#sample usage:
# d = SizedDict()
# for i in xrange(10000): d[i] = 'test'
# print len(d)

Discussion:

This can be used for caching of data where the amount of data cached really matters. Hosting servers, for instance, can impose ram usage limitations, and where you'd really like to store all the information in memory, sometimes you just can't, but you can certainly compromise. Just replace with a regular dict object when you have the memory to burn.

EDIT: Added the CacheDict class. I decided I needed a quick in-memory cache for when I didn't have mcached interfaces available, and added this to a project I'm working on. Figured it compliments the SizedDict class well.



Add comment

No comments.



Highest rated recipes:

1. A simple XML-RPC server

2. Web service accessible ...

3. IPy Notify

4. Changing return value ...

5. Quantum Superposition

6. Pickle objects under ...

7. Generalized delegates ...

8. Reorder a sequence (uses ...

9. Setting Win32 System ...

10. ObjectMerger




Privacy Policy | Email Opt-out | Feedback | Syndication
© 2006 ActiveState Software Inc. All rights reserved.