views:

219

answers:

3

This is specifically related to the Google App Engine Memcache API, but I'm sure it also applies to other Memcache tools.

The dictionary .get() method allows you to specify a default value, such as dict.get('key', 'defaultval')

This can be useful if it's possible you might want to store None as a value in a dictionary.

However, the memcache.get() does not let you to do this. I've modified my @memoize decorator so it looks like this:

def memoize(keyformat, time=1000000):

    """Decorator to memoize functions using memcache."""
    def decorator(fxn):
        def wrapper(*args, **kwargs):
            key = keyformat + str(args[1:]) + str(kwargs)
            from google.appengine.api import memcache
            data = memcache.get(key)
            if Debug(): return fxn(*args, **kwargs) 
            if data:
                if data is 'None': data =  None
                return data
            data = fxn(*args, **kwargs)
            if data is None: data = 'None' 
            memcache.set(key, data, time)
            return data
        return wrapper
    return decorator

Now I'm sure there's a good argument that I shouldn't be storing None values in the first place, but let's put that aside for now. Is there a better way I can handle this besides converting None vals to strings and back?

+4  A: 

A possible way to do this is to create new class that defines none for this purpose, and assign instances of this to the cache (unfortunately you cannot extend None). In this case, you can check for instances of your None class when you check the result of mc.get(key) (see python's isinstance())

Dana the Sane
I think this is the best approach. It gives you a sentinel value that can't be confused for anything else.
Nick Johnson
This is what I ended up doing. Thanks!
jamtoday
A: 

Not really.

You could store a None value as an empty string, but there isn't really a way to store special data in a memcache.

What's the difference between the cache key not existing and the cache value being None? It's probably better to unify these two situations.

Aaron Gallagher
Actually, it can be useful to distinguish them. For example, suppose I have a (expensive) way to authenticate users, and I cache the results - the user's details - in memcache. If I get back a 'no such user' response, I probably want to cache that negative response, or else a user can DoS my service by trying to log in with invalid usernames over and over.
Nick Johnson
This is exactly the type of situation which I found myself in. Sometimes you want to know that a function returned 'None' but also that it's been done recently enough so that it shouldn't be executed again.
jamtoday
A: 

You could do something like what Haskell and Scala does and store an Option dictionary. The dictionary contains two keys: one key to indicate that it is valid and one key that is used to hold the data. Something like this:

{valid: true, data: whatyouwanttostore}

Then if get return None, you know that the cache was missed; if the result is a dictionary with None as the data, the you know that the data was in the cache but that it was false.

tomjen