开发者

how to rewrite python dicts to get default values

I want to rewrite Python's开发者_StackOverflow dictionary access mechanism "getitem" to be able to return default values.

The functionality I am looking for is something like

a = dict()
a.setdefault_value(None)
print a[100] #this would return none

any hints ?

Thanks


There is already a collections.defaultdict:

from collections import defaultdict

a = defaultdict(lambda:None)
print a[100]


There is a defaultdict built-in starting with Python 2.6. The constructor takes a function which will be called when a value is not found. This gives more flexibility than simply returning None.

from collections import defaultdict

a = defaultdict(lambda: None)
print a[100] #gives None

The lambda is just a quick way to define a one-line function with no name. This code is equivalent:

def nonegetter():
    return None

a = defaultdict(nonegetter)
print a[100] #gives None

This is a very useful pattern which gives you a hash showing the count of each unique object. Using a normal dict, you would need special cases to avoid KeyError.

counts = defaultdict(int)
for obj in mylist:
   counts[obj] += 1


use a defaultdict (http://docs.python.org/library/collections.html#collections.defaultdict)

import collections
a = collections.defaultdict(lambda:None)

where the argument to the defaultdict constructor is a function which returns the default value.

Note that if you access an unset entry, it actually sets it to the default:

>>> print a[100]
None
>>> a
defaultdict(<function <lambda> at 0x38faf0>, {100: None})


If you really want to not use the defaultdict builtin, you need to define your own subclass of dict, like so:

class MyDefaultDict(dict):
    def setdefault_value(self, default):
        self.__default = default
    def __getitem__(self, key):
        try:
            return self[key]
        except IndexError:
            return self.__default


i wasnt aware of defaultdict, and thats probably the best way to go. if you are opposed for some reason ive written small wrapper function for this purpose in the past. Has slightly different functionality that may or may not be better for you.

def makeDictGet(d, defaultVal):
    return lambda key: d[key] if key in dict else defaultVal

And using it...

>>> d1 = {'a':1,'b':2}
>>> d1Get = makeDictGet(d1, 0)
>>> d1Get('a')
1
>>> d1Get(5)
0
>>> d1['newAddition'] = 'justAddedThisOne'    #changing dict after the fact is fine
>>> d1Get('newAddition')
'justAddedThisOne'
>>> del d1['a']
>>> d1Get('a')
0
>>> d1GetDefaultNone = makeDictGet(d1, None)   #having more than one such function is fine
>>> print d1GetDefaultNone('notpresent')
None
>>> d1Get('notpresent')
0
>>> f = makeDictGet({'k1':'val1','pi':3.14,'e':2.718},False) #just put new dict as arg if youre ok with being unable to change it or access directly
>>> f('e')
2.718
>>> f('bad')
False
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜