Jam*_*mes 9 python dictionary defaultdict dictionary-missing
我想知道如何创建宽容字典(如果引发KeyError则返回默认值).
在下面的代码示例中,我将得到一个KeyError; 例如
a = {'one':1,'two':2}
print a['three']
Run Code Online (Sandbox Code Playgroud)
为了不得到一个我将1.必须捕获异常或使用获取.
我不想用我的字典那样做...
Ale*_*lli 22
import collections
a = collections.defaultdict(lambda: 3)
a.update({'one':1,'two':2})
print a['three']
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
... 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
Run Code Online (Sandbox Code Playgroud)
......如你所见,完全可以节省内存开销.当然,性能是另一个问题:
$ 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
Run Code Online (Sandbox Code Playgroud)
由于defaultdict在查找时添加了(先前丢失的)密钥,因此在下次查找这样的密钥时会更快,而mydict(__missing__每次覆盖以避免添加)会支付"缺少密钥查找开销".
当然,您是否关心任何问题(性能与内存占用量)完全取决于您的具体用例.无论如何,要注意权衡这一点是个好主意! - )
版本2.5中的新增内容:如果dict的子类定义方法__missing __(),则如果不存在键键,则d [key]操作将使用键键作为参数调用该方法.然后,如果密钥不存在,则d [key]操作返回或引发__missing __(key)调用返回或引发的任何内容.没有其他操作或方法调用__missing __().如果未定义__missing __(),则引发KeyError.__missing __()必须是一个方法; 它不能是实例变量.有关示例,请参阅collections.defaultdict.
http://docs.python.org/library/stdtypes.html
以下是dictNullUserException建议的子类化方法
>>> class forgiving_dict(dict):
... def __missing__(self, key):
... return 3
...
>>> a = forgiving_dict()
>>> a.update({'one':1,'two':2})
>>> print a['three']
3
Run Code Online (Sandbox Code Playgroud)
这个答案和Alex之间的一个很大区别是缺少的密钥没有添加到字典中
>>> print a
{'two': 2, 'one': 1}
Run Code Online (Sandbox Code Playgroud)
如果你期待很多失误,这是非常重要的
| 归档时间: |
|
| 查看次数: |
677 次 |
| 最近记录: |