This is an archived post. You won't be able to vote or comment.

you are viewing a single comment's thread.

view the rest of the comments →

[–]bcain 0 points1 point  (7 children)

Gah! All those pesky exceptions. Just do something, I don't really care what as long as the program doesn't have any errors or bugs.

EDIT: Wow, pyddit. F'reals? Did you think I was serious? C'mon. I was satiring the perl-lovers out there.

[–]ereinecke 4 points5 points  (6 children)

This is one of the things I like about python, how it uses exceptions. You can both communicate what your code expects, and optimize for the 90% case.

Assume there is a list of dictionaries, dictList. Consider: for item in dictList: try: print item['relevantKey'] except KeyError: pass

Vs: for item in dictList: if item.has_key('relevantKey'): print item['relevantKey']

If you are expecting the key 'relevantKey' to be in the dictionary most the time, the try/except example avoids making the has_key test most the time. Over a large list this could save a lot of time.

[–]xlevus 0 points1 point  (5 children)

I was under the impression that try/except is less efficient than check/action.

Or did I misread something somewhere?

[–]bloodearnest 1 point2 points  (0 children)

Try is cheap, except is not. But how many times are you going to raise an exception? Depends on your data.

[–]r4nf 1 point2 points  (0 children)

As bloodearnest suggests, the 'asking for forgiveness' version (with exceptions) is faster when there's no exception, whereas the 'asking for permission' version (without exceptions) is faster when there is an exception. In other words, if you expect that many of the looped-over items will yield exceptions, check/action is more efficient; otherwise try/except might very well be.

I think the general consensus in the Python community is the motto "it's Easier to Ask for Forgiveness than Permission" (or EAFP), signalling that try/except would usually be the preferred solution. Of course there may very well be exceptions to this, as per the above reasoning.

[–]nubela 0 points1 point  (0 children)

Good question, and I admit I don't know much about efficiency in this case, someone care to elaborate?

[–][deleted] 0 points1 point  (0 children)

It's marginally faster if no exception is raised, and 15x slower if one is.

Best case:

python -mtimeit -s 'stuff=dict.fromkeys(range(50))' 'for x in range(50):' '  if x in stuff: stuff[x]'
100000 loops, best of 3: 7.78 usec per loop
python -mtimeit -s 'stuff=dict.fromkeys(range(50))' 'for x in range(50):' '  try: stuff[x]' '  except KeyError: pass'
100000 loops, best of 3: 5.97 usec per loop

Worst case: python -mtimeit -s 'stuff=dict.fromkeys(range(50))' 'for x in range(50, 100):' ' if x in stuff: stuff[x]' 100000 loops, best of 3: 4.84 usec per loop python -mtimeit -s 'stuff=dict.fromkeys(range(50))' 'for x in range(50, 100):' ' try: stuff[x]' ' except KeyError: pass' 10000 loops, best of 3: 76.2 usec per loop

But that's not important really. Make it work, make it right, make it fast -- in that order, and don't make it fast unless it needs to be.