Python:尝试除了KeyError vs if has_key()

时间:2012-09-09 20:45:15

标签: python performance

在下面的代码中,什么更有效/更'Pythonic'?使用try-catch子句或if-else子句?

fname = 'AdobeARM.log'

letters = {}

with open(fname,'r') as f:
    for line in f:
        for c in line:
            try:
                letters[c] += 1
            except KeyError:
                letters[c] = 1

print letters

VS

fname = 'AdobeARM.log'

letters = {}

with open(fname,'r') as f:
    for line in f:
        for c in line:
            if letters.has_key(c):
                letters[c] += 1
            else:
                letters[c] = 1

print letters

我倾向于使用try catch选项,但我不确定原因。

4 个答案:

答案 0 :(得分:21)

使用dict.get()

  

get(key[, default])

     

如果key在字典中,则返回key的值,否则返回default。如果   未给出default,默认为None,因此此方法永远不会   提出KeyError

换句话说,d.get('x', c)相当于d['x'] if 'x' in d else c

示例:

In [24]: d = {'a':1, 'b':2}

In [27]: d['d'] = d.get('d', 0) + 1  # 0 is the default value

In [28]: d
Out[28]: {'a': 1, 'b': 2, 'd': 1}

In [29]: d['d'] = d.get('d', 0) + 1

In [30]: d
Out[30]: {'a': 1, 'b': 2, 'd': 2}

答案 1 :(得分:16)

根据你的python版本,你可能想在这里使用defaultdictCounter,因为它是最合适的。

现在,关于哪种替代品是最蟒蛇的,它取决于你要问的人。一方面,exception-based flow control is sometimes frowned upon,因为异常应该在特殊情况下提出,而不是用作条件。

然而,另一方面,有situations in which you would rather use try / except,因为条件不实用。

最后,从性能的角度来看,这取决于你是否希望你的密钥在大多数时间都存在(一个if语句有点慢,但是一个例外是慢很多当< / em>它被提升了),如果考虑到性能,你应该在决定之前用两种实现来衡量你的表现。


总而言之,我认为一般的经验法则是默认使用条件,但如果它们更实用/更有意义/给你真正需要的加速,则使用例外。

答案 2 :(得分:10)

更多pythonic是使用专用工具:

from collections import Counter

with open(fname, 'r') as f:
    letters = Counter(f.read())

另请注意,has_key已弃用,以支持in

答案 3 :(得分:0)

看看你是否可以使用这个技巧来pythonically地处理异常。

adict = {}
default = None
val = adict.get('dogname', default)
# val will be None rather than raise an exception.

参考:https://wiki.python.org/moin/KeyError