Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

To authors: I would avoid try except in this code snippet, a simple if else is more explicit. I would also avoid a = b = c statement. One line per statement is better most of the time.


The Python community generally advocates an "it's easier to ask for forgiveness than permission" coding style. When faced with a condition of the form "if condition a holds, do b, else c", it's very often a better idea to do "let's try b, and do c in case b fails because condition a didn't hold".

In this case it's better because you can avoid computing an extra hash of the object in cases where it's already a key of the dictionary. This may seem like a silly optimization, but it can very easily add up if you're accessing existing elements most of the time--I once had a bit of code that went 60x faster when I replaced an if-else with a try-except.

In other cases it can be even more beneficial. Say you're opening a file. One approach to avoid errors would be to check if a file exists first. This is error-prone because the file might cease to exist in between the 'if' and the 'open' statements, and now you have no code written to handle the error. Using try-except will ensure that you actually handle the error intelligently.

This isn't to say there's never a good reason to use an 'if' to check things, just that if you can do it in one step instead of two, one is usually better.


Agree with that "try except" is better than "if else" for file handling ("with" is even better).

I am not sure if "try except" is really faster than "if else" in some edge cases in a memoization context, as you claim.

What I am sure is that in a didactic context, where you want people to understand code, something like:

    if args not in stored_results:
        stored_results[args] = fn(*args)

    return stored_results[args]
is much better than that (from the OP):

    try:
        # try to get the cached result
        return stored_results[args]
    except KeyError:
        # nothing was cached for those args. let's fix that.
        result = stored_results[args] = fn(*args)
        return result


For a memoize function, try/except is perfect. You gain a slight speed benefit from function calls that are memoized as compared to the "if x not in y", and since memoize is all about speeding up repetitive function calls, it's the most optimal choice. Using the "if x not in y" you are giving up speed of the "x is actually in the y" in exchange for a cheaper than "except", however if you are memoizing a function, chances are that the function is going to eat up processing power making your optimization of the "exceptional case" at the expense of the "normal case" not worth it.

As far as people understanding code - this is a common pattern in python code, try / except should be easy for anyone to understand.


Out of curiosity, in a situation where you are doing negligible condition testing, is try–except still considered "more performant" than if–else flow control? For some reason (and I'm going to do so reading to get clarity on this point), I have had the silly notion that throwing and handling exceptions can be costly.


I don't think the try-except is 'more performant'. At least from the below benchmark test it doesn't seem to be so.

  >>> from timeit import timeit
  >>> timeit(setup='x=dict([(i,i*2) for i in range(10)])',stmt=
       """
          if 20 in x:
             pass""")

  0.07420943164572691

  >>> timeit(setup='x=dict([(i,i*2) for i in range(10)])',
       stmt="""
               try:
		  x[20]
               except KeyError:
		  pass""")

  1.1514457843105674


I am on my phone and cannot test this, but the try:except: construct is optimised for the non-exceptional path. The latter is probably faster for x[0] than x[20].


I'm no pythonist, but I think setdefault would be perfect for the case

http://docs.python.org/library/stdtypes.html#dict.setdefault


I agree. The author uses exception for something that is not at all exceptional. In fact, it will occur at least once. This is misuse of an exception. No one expects Spanish Exception!

Earlier, he uses the map function for no apparent reason. I mean - list comprehension would perfectly fit here.

I still think I have something to learn from the article, though.


The try/except is the preferred python way of doing things. In Python, try/except is cheap, and in the case where the try actually succeeds, you can gain a slight performance benefit. In this case, since performance is the goal, it is perfect for memoize.


I think subtle optimization should be left aside in a tutorial. Try except is a good way to handle many cases that are not exceptions, like when reaching the end of an iteration, but I never heard that it was "the preferred way" for checking the presence of a key in a dict. I believe the "if in" construct is cleaner, clearer and "pythoniker", if you don't mind the Housism.


"if in" is not the preferred way to check for the presence of a key in a dict. You should use setdefault. The thing is, you aren't searching for a key in a dict only. You're memoizing. And try/except is the most efficient way to do that. This article isn't teaching you how to program, it's teaching decorators.




Consider applying for YC's Winter 2026 batch! Applications are open till Nov 10

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: