Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python: try except KeyError vs if has_key() [duplicate]

In the following code, what's more efficient / more 'Pythonic'? using a try-catch clause or a if-else clause?

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

I tend to go with the try catch option, but I'm not sure why.

like image 536
zenpoy Avatar asked Sep 09 '12 20:09

zenpoy


3 Answers

Use dict.get():

get(key[, default])

Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.

In other words d.get('x', c) is equivalent to d['x'] if 'x' in d else c.

Example:

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}
like image 67
Ashwini Chaudhary Avatar answered Nov 20 '22 05:11

Ashwini Chaudhary


Depending on your python version, you might want to use a defaultdict or a Counter here, as it's the most appropriate.

Now, regarding which alternative is the most pythonic, it depends on the people you're going to ask. On the one hand, exception-based flow control is sometimes frowned upon, as exceptions are supposed to be raised in exceptional situations, and not to be used as conditionals.

On the other hand, however, there are situations in which you would rather use try / except because conditionals would not be practical.

Finally, from a performance standpoint, it depends on whether you expect your key to be there most of the time (An if statement is a bit slower, but an exception is a lot slower when it's raised), and if performance is a concern, you should measure your performance with both implementations before deciding.


All in all, I think that a general rule of thumb would be to use conditionals by default, but use exceptions if they are more practical / make more sense / give you speedups that you really need.

like image 42
Thomas Orozco Avatar answered Nov 20 '22 05:11

Thomas Orozco


More pythonic is to use a dedicated tool for the job:

from collections import Counter

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

Also do note that has_key is deprecated in favor of in.

like image 10
georg Avatar answered Nov 20 '22 03:11

georg