← Back to context

Comment by bee_rider

2 years ago

I believe that’s the conventional approach in Python, though? It is a duck-typing language, try-except is a legitimate way of seen if an operator works on an object, and objects should do sensible things with operators.

The funny example is that the hasattr built-in just tries to getattr, and then catches the exception to tell if it has the attribute.

I agree. In Python terms "Easier to Ask for Forgiveness than Permission" (EAFP) is preferred over "Look Before You Leap" (LBYL).

https://docs.python.org/3/glossary.html#term-EAFP comments:

> Easier to ask for forgiveness than permission. This common Python coding style assumes the existence of valid keys or attributes and catches exceptions if the assumption proves false. This clean and fast style is characterized by the presence of many try and except statements. The technique contrasts with the LBYL style common to many other languages such as C.

and there are any number of essays on the topic, like (random DDG search) https://programmingduck.com/articles/lbyl-eafp .

Exceptions are for exceptional circumstances. An object being a certain type is not an exceptional circumstance, not even in a dynamic language. You should never be surprised by the type of an object unless your program has serious design flaws.

The fact that the language doesn't have your back means you need to be more careful about types, not less. The type of the arguments is a function precondition. It's the callee's responsibility to document preconditions and ideally recover cleanly from a violation, but the caller's responsibility to ensure preconditions are met. Illegal states should be caught early, not allowed to percolate until an exception is thrown.

I don't much care if what I just wrote is "Pythonic" or not. I don't think too much careful design up front is responsible for every Python codebase I've ever seen reading like Finnegan's Wake.

  • You aren’t required to like the conventional way they do things in Python.

    I dunno. I don’t love Python for big projects either. If we want to go around and tell all the people using this very popular language to stop shipping their successful products because they look messy to us, I’ll happily take the second shift (after you), haha.

If you are calling something immediately, a try-except is ok. If you are calling with a try-except just to simulate hasattr or getattr then why do we have the built-ins in the first place?

  • “Just try and then handle the exception” is a pretty weird paradigm for this sort of thing, to those of us who come from more typical languages. So I suspect they just included hasattr to make us more comfortable.

Conventions are changing. Modern python is shifting to type checking with external type checkers.

  • The two are not incompatible. I'll type all class properties and functions, but still use try/except on dict access or function calls.

    • It's not about incompatibility it's about safety. You drive with air bags or you don't, those two concepts are NOT about incompatibility. It doesn't even make sense.

      If there are situations where you have no choice but to drive without airbags, those are holes in safety.

      Essentially if you have to have runtime checks to prevent the program from full on crashing those are holes. Not everything is checkable with static checks but the way to go is to move as much of your code away from runtime checks as much as possible.

      2 replies →