Python 宽容的字典
我想知道如何创建宽恕字典(如果出现KeyError,它将返回默认值) 在下面的代码示例中,我会得到一个KeyError;比如说Python 宽容的字典,python,dictionary,defaultdict,dictionary-missing,Python,Dictionary,Defaultdict,Dictionary Missing,我想知道如何创建宽恕字典(如果出现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'] 根据需要
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
进行子类化,并覆盖\uuuuuuu missing\uuuuuuuu
,但是当defaultdict
行为(忽略正在查找的确切缺失键)非常适合您时,这就没有多大意义了
编辑…除非,也就是说,您担心一个
在每次查找缺少的键(这是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
(它覆盖\uuuuuuu缺少的
以避免添加)每次都会支付“缺少的键查找开销”
当然,您是否关心这两个问题(性能与内存占用)完全取决于您的特定用例。在任何情况下,注意权衡都是一个好主意!-)
版本2.5中新增:如果
dict定义了一个方法uuu缺少uuu(),
如果钥匙不存在,则
d[key]操作调用该方法
以键作为参数。这个
d[键]操作然后返回或
引发返回或引发的任何内容
如果
钥匙不存在。没有别的
操作或方法调用
__缺少\ \()。如果未定义uuu missing_uuuu(),则会引发KeyError。
__缺少的\必须是一个方法;它不能是实例变量。为了
示例,请参见collections.defaultdict
您可能需要使用defaultdict(我相信它至少需要python2.5)
传递给构造函数的函数告诉类返回什么作为默认值。有关其他示例,请参见。以下是如何按照NullUserException的建议对
dict
进行子类化
>>> class forgiving_dict(dict):
... def __missing__(self, key):
... return 3
...
>>> a = forgiving_dict()
>>> a.update({'one':1,'two':2})
>>> print a['three']
3
这个答案与Alex的答案之间的一大区别是缺少的键不是添加到字典中的
>>> print a
{'two': 2, 'one': 1}
如果您期望大量未命中,这一点非常重要。有时您真正想要的是
.setdefault()
,这不是很直观,但它是一种“返回指定的键,如果它不存在,请将该键设置为此值”的方法
下面是一个使用setdefault()
效果良好的示例:
collection = {}
for elem in mylist:
key = key_from_elem(elem)
collection.setdefault(key, []).append(elem)
这将允许我们创建这样一个字典:
{'key1':[elem1,elem3],'key2':[elem3]}
无需进行丑陋的检查以查看是否已经存在密钥并为其创建列表。集合。defaultdict
是您的电池内置解决方案。警告:defaultdict在返回给定密钥的默认值时会将新项插入自身。这就把读操作变成了潜在的写操作,这意味着查找大量丢失的键将使其快速增长。棒极了!从第二段到最后一段似乎与您的示例不相关,因为您从未使用同一个键两次。因此,即使您从不重复某个键,defaultdict似乎也会更快,如果您重复了,则会更快。是这样吗?@Jeff,timeit
循环您正在测量的语句,因此它重复该语句——在本例中,for i in r
循环。+1我从未意识到这两种方法的性能/内存权衡。谢谢你启发我。
collection = {}
for elem in mylist:
key = key_from_elem(elem)
collection.setdefault(key, []).append(elem)