Подтвердить что ты не робот

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, но я не уверен, почему.

4b9b3361

Ответ 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