18

在下面的代码中,什么更高效/更“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

4 回答 4

23

使用dict.get()

get(key[, default])

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}
于 2012-09-09T20:46:23.353 回答
17

根据您的 python 版本,您可能希望在此处使用 adefaultdict或 a Counter,因为它是最合适的。

现在,关于哪种选择是最 Pythonic 的,这取决于你要问的人。一方面,基于异常的流控制有时不受欢迎,因为异常应该在异常情况下引发,而不是用作条件。

但是,另一方面,在某些情况下,您宁愿使用 try / except,因为条件语句不实用。

最后,从性能的角度来看,这取决于您是否希望您的密钥大部分时间都在那里(if语句有点慢,但引发异常会慢很多),如果性能是一个问题,您在决定之前,应该衡量你在这两种实现中的表现。


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

于 2012-09-09T20:52:47.080 回答
10

更多的pythonic是使用专门的工具来完成这项工作:

from collections import Counter

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

另请注意,has_key不赞成使用in.

于 2012-09-09T20:52:37.377 回答
1

看看你是否可以使用这个技巧以 python 方式处理异常。

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

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

于 2014-04-18T19:14:47.763 回答