web-dev-qa-db-fra.com

Python: essayez sauf KeyError vs if has_key ()

Dans le code suivant, quoi de plus efficace/plus 'Pythonic'? utiliser une clause try-catch ou une clause 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

J'ai tendance à choisir l'option try catch, mais je ne sais pas pourquoi.

17
zenpoy

En fonction de votre version de Python, vous pouvez utiliser ici un defaultdict ou un Counter , car c'est le plus approprié. 

Maintenant, en ce qui concerne quelle alternative est la plus pythonique, cela dépend des personnes que vous allez demander. D'une part, le contrôle de flux basé sur les exceptions est parfois mal vu }, car les exceptions sont supposées être levées dans des situations exceptionnelles, et ne doivent pas être utilisées comme conditionnelles.

Par contre, il existe situations dans lesquelles vous préféreriez utiliser try/except parce que les conditions ne seraient pas pratiques.

Enfin, du point de vue des performances, cela dépend si vous attendez que votre clé soit là la plupart du temps (une instruction if est un peu plus lente, mais une exception est beaucoup plus lente quand elle est levée), et si les performances Avant de prendre votre décision, vous devez mesurer votre performance avec les deux implémentations.


Globalement, je pense qu’une règle générale serait d’utiliser des conditions conditionnelles par défaut, mais d’utiliser des exceptions si elles sont plus pratiques/plus logiques/vous donnent les accélérations dont vous avez réellement besoin.

15
Thomas Orozco

Utilisez dict.get() :

get(key[, default])

Renvoie la valeur de la clé si key est dans le dictionnaire, sinon default. Si default n'est pas indiqué, sa valeur par défaut est None, de sorte que cette méthode ne génère jamais de KeyError.

En d'autres termes, d.get('x', c) est équivalent à d['x'] if 'x' in d else c.

Exemple:

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}
21
Ashwini Chaudhary

Plus Pythonic est d'utiliser un outil dédié pour le travail:

from collections import Counter

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

Notez également que has_key est déconseillé au profit de in.

10
georg

voyez si vous pouvez utiliser cette astuce pour gérer les exceptions pythoniquement. 

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

Référence: https://wiki.python.org/moin/KeyError

0
Alan Dong