import collections
a = collections.defaultdict(lambda: 3)
a.update({'one':1,'two':2})
print a['three']
< p >发出所需的
3
。 您还可以自己子类化
dict
并覆盖
__missing__
,但是当
defaultdict
行为(忽略正在查找的确切缺失键)非常适合您时,这没有多大意义...
编辑...除非你担心每次查找缺失键(这是defaultdict
的语义之一)都会使a
增加一个条目,并希望获得更慢的行为但节省一些内存。 例如,就内存而言...:
>>> import sys
>>> a = collections.defaultdict(lambda: 'blah')
>>> print len(a), sys.getsizeof(a)
0 140
>>> for i in xrange(99): _ = a[i]
...
>>> print len(a), sys.getsizeof(a)
99 6284
...defaultdict最初为空,现在具有我们查找的99个先前缺失的键,并且占用6284字节(与它为空时占用的140字节相比)。
另一种方法是...
>>> class mydict(dict):
... def __missing__(self, key): return 3
...
>>> a = mydict()
>>> print len(a), sys.getsizeof(a)
0 140
>>> for i in xrange(99): _ = a[i]
...
>>> print len(a), sys.getsizeof(a)
0 140
完全消除了这种内存开销,正如您所见。当然,性能是另一个问题:
$ python -mtimeit -s'import collections; a=collections.defaultdict(int); r=xrange(99)' 'for i in r: _=a[i]'
100000 loops, best of 3: 14.9 usec per loop
$ python -mtimeit -s'class mydict(dict):
> def __missing__(self, key): return 0
> ' -s'a=mydict(); r=xrange(99)' 'for i in r: _=a[i]'
10000 loops, best of 3: 92.9 usec per loop
defaultdict
会在查找时添加(之前不存在的)键,因此当下次查找该键时,它会变得更快,而mydict
(覆盖了__missing__
以避免该添加)则每次都需要支付“缺失键查找开销”。
当然,你是否关心这两个问题(性能与内存占用)完全取决于你的具体用例。无论如何,意识到这种权衡是一个好主意!-)
collections.defaultdict
是一个内置的解决方案。 - Nathan Ernst