我想知道如何创建宽容字典(如果引发 KeyError 则返回默认值的字典)。
在下面的代码示例中,我会得到一个 KeyError;例如
a = {'one':1,'two':2}
print a['three']
为了不得到一个,我会 1. 必须捕获异常或使用 get。
我不想用我的字典做那件事......
最佳答案
import collections
a = collections.defaultdict(lambda: 3)
a.update({'one':1,'two':2})
print a['three']
根据需要发出 3
。您也可以自己子类化 dict
并覆盖 __missing__
,但是当 defaultdict
行为(忽略确切丢失的键是正在查找)非常适合你...
编辑 ...除非,也就是说,您担心每次查找缺失项时 a
都会增长一个条目键(它是 defaultdict
语义的一部分)并且宁愿获得更慢的行为但节省一些内存。例如,在内存方面...:
>>> 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__
以避免添加)每次都支付“丢失的 key 查找开销”。
当然,您是否关心这两个问题(性能与内存占用)完全取决于您的具体用例。在任何情况下,了解权衡都是一个好主意!-)
关于python - 一本宽容的字典,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3358580/