Python: попробуйте кроме KeyError vs if has_key()
В следующем коде, что более эффективно/более "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, но я не уверен, почему.
Ответы
Ответ 1
В зависимости от вашей версии python вы можете использовать defaultdict
или Counter
здесь, как наиболее подходящий.
Теперь, в отношении того, какая альтернатива является самой пифонической, это зависит от людей, которых вы спросите. С одной стороны, управление потоком на основе исключений иногда недооценивается, поскольку исключения должны быть подняты в исключительных ситуациях и не должны использоваться в качестве условных обозначений.
С другой стороны, существуют ситуации в которых вы предпочитаете использовать try/except, поскольку условные выражения не будут практичными.
Наконец, с точки зрения производительности это зависит от того, хотите ли вы, чтобы ваш ключ находился там большую часть времени (оператор An if
немного медленнее, но исключение намного медленнее, когда оно поднимается), и если производительность является проблемой, вы должны измерить свою производительность с обеих реализаций до принятия решения.
В целом, я думаю, что общим правилом будет использование условных выражений по умолчанию, но используйте исключения, если они более практичны/имеют больше смысла/дают вам ускорения, которые вам действительно нужны.
Ответ 2
Используйте dict.get()
:
get(key[, default])
Возвращает значение для ключа, если key
находится в словаре, иначе default
. Если default
не указывается, по умолчанию он равен None
, так что этот метод никогда поднимает a 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}
Ответ 3
Больше pythonic - использовать выделенный инструмент для задания:
from collections import Counter
with open(fname, 'r') as f:
letters = Counter(f.read())
Также обратите внимание, что has_key
устарел в пользу in
.
Ответ 4
посмотрите, можете ли вы использовать этот трюк для обработки исключения pythonically.
adict = {}
default = None
val = adict.get('dogname', default)
# val will be None rather than raise an exception.
Ссылка: https://wiki.python.org/moin/KeyError