Is checking for the existence of a key in a dictionary better than catching a KeyError in Python?
我在Python方面有一些经验,但我正在参加Udacity计算机科学课程,以填补我所学的空白,补充我已经知道的内容。课程介绍了一个哈希表查找函数,如果键不在哈希表中,该函数将不返回键的值。当键不存在时,python的字典类型会抛出一个keyerror,因此课程建议在获取值之前使用key in mydict。
我想知道的是,这样做是否更好:
1 2 3 4 5 6 7
| mydefaultval = 75
key = ..
mydict = ..
if key in mydict:
val = mydict[key]
else:
val = mydefaultval |
…或
1 2 3 4 5 6 7
| mydefaultval = 75
key = ..
mydict = ..
try:
val = mydict[key]
except KeyError:
val = mydefaultval |
我可以想象,为了让Python检查这个键是否存在,它必须在字典中找到它。如果我在那个键上获取值,它必须做同样的事情两次。我这样想是正确的,还是python会做其他的事情?
- 内德给了你正确的答案——但是值得建议的是,你不应该隐藏内置的东西(比如命名一个dict-dict)。一般来说,python遵循的是"最好请求原谅而不是允许",而不是"三思而后行"的方法。也就是说,不知道你能不能先做,试着去做,如果不能,那就去做。
- @琼斯门茨,对不起,忘记了。我只是想快速输入示例。
- 虽然在你的情况下还有其他的答案,但乔恩·克莱门茨是对的——你几乎总是能更好地抓住例外——首先,它通常显示了正确的优先权——当一切如你所料时,你想处理发生的事情,而不是考虑检查。它还可以避免在各种情况下的比赛条件,这是值得做的,因为如果它们滑入的话,它们是很微妙和烦人的虫子。
- Lattyware,这是我没有想到的另一件事。你是说,在检查它的存在之后,在获得它的值之前,有可能删除密钥,对吗?
- 是的-这通常不是像dict键这样的问题,但是在涉及线程的地方,或者在文件中写入/读取,这是一个严重的问题。一般来说,最好还是坚持处理异常,而不是以前检查,除非您绝对需要(例如,如果代码的那一部分是一个关键的瓶颈,异常情况实际上发生了很多-尽管请注意,如果异常情况大部分时间都发生,您可能能够交换异常CA的内容E是另一种选择——但很明显,除非你必须这样做,否则永远不要乐观。
最好是使用dict.get:
1
| val = my_dict.get(key, mydefaultval) |
如果没有一个很棒的方法,我建议使用例外。Python文化是例外是不被禁止的,而且通常明确的检查实际上会捕获异常。
- 你会说,这适用于支持检查键的函数而不是获取默认值的其他语言吗?
- 如果它是性能关键的,并且没有这样一个很棒的方法,那么只有当我期望值通常是存在的时候,我才会使用这个异常。但最好先编写最清晰的代码,如果发现瓶颈,就要担心性能问题。
- @史蒂文伦巴斯基,你的意思是相反的吗?只有在期望值通常不存在时才使用异常?
- 另外,Ned,感谢您回答这个问题,即使内置函数存在。
- 值得注意的是,dict.get()的实现不是一成不变的。欢迎实现将其有效地构造为try/except块。不过,我已经很久没有深入研究过Python实现的源代码了,所以它们可能在幕后做了一些更聪明的事情。
如果每次使用特定dict时,默认值都相同,则另一个选项是使用collections.defaultdict。声明dict比dict.get()解决方案更为冗长,但使用起来更为简洁:
1 2 3 4
| >>> from collections import defaultdict
>>> mydict = defaultdict( lambda: 75 )
>>> mydict[3]
75 |