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.
Use dict.get()
:
get(key[, default])
Return the value for key if
key
is in the dictionary, elsedefault
. Ifdefault
is not given, it defaults toNone
, so that this method never raises aKeyError
.
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}
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.
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With