请稍侯

使用collections.defaultdict

12 March 2015

defaultdict Examples

collections.defaultdictdict的一个子类,定义是

class collections.defaultdict([default_factory[, ...]]) 

至少提供一个参数,这个参数会初始化给dict的default_factory属性,这个属性在dict中默认为None,如果这个返回的值为空的话会导致的引发KeyError异常.

>>> d = dict()
>>> print d['x']
Traceback (most recent call last):
  File "G:\PythonTest\test1.py", line 2, in <module>
    print d['x']
KeyError: 'x'

再说一下default_factory属性,是在__missing__()函数中使用的,通过构造函数初始化而来。 对于__missing__(key)函数:

>>> from collections import defaultdict
>>> print defaultdict.__missing__.__doc__
    __missing__(key) # Called by __getitem__ for missing key; pseudo-code:
        if self.default_factory is None: raise KeyError(key)
        self[key] = value = self.default_factory()
        return value

可以看出当使用__getitem__()方法访问一个不存在的键时(dict[key]这种形式实际上是__getitem__()方法的简化形式),会调用__missing__()方法获取默认值,并将该键添加到字典中去。dict会使用__getitem__()来返回值,值不存在会返回None而不是default_factory。在key值不存在的条件下,如果default_factory不为None,会使用default_factory构造一个默认值,赋值给dict[key]

example 1

>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
>>> d = defaultdict(list)  # 默认初始化为list
>>> for k, v in s:
        # k不存在的时候会创建一个空的list给d[k],然后d[k]就返回一个list,可以进行append
...     d[k].append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

example 2

dict.setdefault()方法接收两个参数,第一个参数是健的名称,第二个参数是默认值。假如字典中不存在给定的键,则返回参数中提供的默认值;反之,则返回字典中保存的值。

>>> d = {}
>>> for k, v in s:
...     d.setdefault(k, []).append(v)
...
>>> d.items()
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])]

example 3

字符第一次出现,dict中没有键值,default_factory调用int()构造一个默认值

>>> s = 'mississippi'
>>> d = defaultdict(int)
>>> for k in s:
        # 统计某个字符出现的次数,如果不使用defaultdict(int)而使用dict,会出现KeyError
...     d[k] += 1
...
>>> d.items()
[('i', 4), ('p', 2), ('s', 4), ('m', 1)]

example 4

可以通过函数初始化: itertools.repeat(value).nextitertools.repeat一个函数,传入的是函数名,确保能够被调用

>>> def constant_factory(value):
...     return itertools.repeat(value).next
>>> d = defaultdict(constant_factory('<missing>'))
>>> d.update(name='John', action='ran')
>>> '%(name)s %(action)s to %(object)s' % d # name匹配dict中的key
'John ran to <missing>'
>>> print d
defaultdict(<method-wrapper 'next' of itertools.repeat object at 0x00000000022F8B38>, 
{'action': 'ran', 'object': '<missing>', 'name': 'John'})

example 5

>>> s = [('red', 1), ('blue', 2), ('red', 3), ('blue', 4), ('red', 1), ('blue', 4)]
>>> d = defaultdict(set)
>>> for k, v in s:
...     d[k].add(v)
...
>>> d.items()
[('blue', set([2, 4])), ('red', set([1, 3]))]