Ava*_*esh 41 python dictionary
可能重复:
'has_key()'或'in'?
我有一个Python字典,如:
mydict = {'name':'abc','city':'xyz','country','def'}
Run Code Online (Sandbox Code Playgroud)
我想检查密钥是否在字典中.我很想知道从以下两个案例中哪个更为可取,为什么?
1> if mydict.has_key('name'):
2> if 'name' in mydict:
Run Code Online (Sandbox Code Playgroud)
Tim*_*ker 66
if 'name' in mydict:
Run Code Online (Sandbox Code Playgroud)
是首选的pythonic版本.has_key()不鼓励使用,并且已在Python 3中删除了此方法.
Mik*_*ham 30
与martineau的回应一样,最好的解决方案通常是不检查.例如,代码
if x in d:
foo = d[x]
else:
foo = bar
Run Code Online (Sandbox Code Playgroud)
通常是写的
foo = d.get(x, bar)
Run Code Online (Sandbox Code Playgroud)
这更短,更直接地说明你的意思.
另一个常见的情况是
if x not in d:
d[x] = []
d[x].append(foo)
Run Code Online (Sandbox Code Playgroud)
这可以改写
d.setdefault(x, []).append(foo)
Run Code Online (Sandbox Code Playgroud)
或者通过使用collections.defaultdict(list)for d和write来改写甚至更好
d[x].append(foo)
Run Code Online (Sandbox Code Playgroud)
aar*_*ing 13
在字节码方面,in保存LOAD_ATTR并替换CALL_FUNCTIONa COMPARE_OP.
>>> dis.dis(indict)
2 0 LOAD_GLOBAL 0 (name)
3 LOAD_GLOBAL 1 (d)
6 COMPARE_OP 6 (in)
9 POP_TOP
>>> dis.dis(haskey)
2 0 LOAD_GLOBAL 0 (d)
3 LOAD_ATTR 1 (haskey)
6 LOAD_GLOBAL 2 (name)
9 CALL_FUNCTION 1
12 POP_TOP
Run Code Online (Sandbox Code Playgroud)
我的感觉是in是很多更具可读性,是我能想到的每一种情况下是首选.
在性能方面,时序反映了操作码
$ python -mtimeit -s'd = dict((i, i) for i in range(10000))' "'foo' in d"
10000000 loops, best of 3: 0.11 usec per loop
$ python -mtimeit -s'd = dict((i, i) for i in range(10000))' "d.has_key('foo')"
1000000 loops, best of 3: 0.205 usec per loop
Run Code Online (Sandbox Code Playgroud)
in 差不多快了两倍.
mar*_*eau 10
我的回答是"都不是".
我认为最"Pythonic"做事的方法是不事先检查密钥是否在字典中,而只是编写假定它在那里的代码并捕获任何因为它不被引发而引起的KeyErrors.
这通常是通过将代码包含在一个try...except子句中来完成的,并且是一个众所周知的习惯用法,通常表达为" 请求宽恕而不是权限 "或缩写为EAFP,这基本上意味着最好尝试一些并抓住错误在做任何事之前确保一切正常.当您可以优雅地处理异常而不是试图避免它们时,为什么验证不需要验证的内容?因为它通常更具可读性,并且如果概率很低,代码往往会更快,因此密钥将不存在(或者可能存在任何先决条件).
当然,这并不适用于所有情况,并不是每个人都同意这一理念,因此您需要根据具体情况自行决定.毫不奇怪,与此相反的是LBYL的"Look Before You Leap".
作为一个简单的例子考虑:
if 'name' in dct:
value = dct['name'] * 3
else:
logerror('"%s" not found in dictionary, using default' % name)
value = 42
Run Code Online (Sandbox Code Playgroud)
VS
try:
value = dct['name'] * 3
except KeyError:
logerror('"%s" not found in dictionary, using default' % name)
value = 42
Run Code Online (Sandbox Code Playgroud)
虽然在这种情况下它几乎完全相同的代码量,但第二个不花时间检查第一个并且可能稍微快一点因为它(尝试...除了块不是完全免费的,所以它可能不在这里做出很大的改变).
一般来说,提前进行测试通常可以更多地参与进来,而不进行测试可以节省大量成本.也就是说,if 'name' in dict:其他答案中陈述的原因更好.
如果你感兴趣的话题,这个消息 "标题(再次:有点遗憾至今)EAFP VS LBYL "从Python邮件列表归档或许可以解释两者的区别走近比我这里有.在关于标题为" 错误检查策略 "的异常章节中,Alex Martelli的第二版Ed-Nutshell中的两种方法也有很好的讨论.
| 归档时间: |
|
| 查看次数: |
88342 次 |
| 最近记录: |