On Tue, Nov 30, 2010 at 3:35 AM, Bill Janssen firstname.lastname@example.org wrote:
Steven D'Aprano email@example.com wrote:
since at least Python 1.5. It's been long considered "best practice" under many circumstances to catch exceptions rather than to try to preemptively guess what might go wrong.
You're kidding, right? *Programming* is about preemptively guessing what might go wrong :-).
LBYL (Look Before You Leap) and EAFPI (Easier to Ask Forgiveness than Permission) is a style argument that is never going to go away though, since the answer is "it depends".
My personal answer is usually "make the common case fast". That means defaulting to using a try-except block (with an else clause to prevent overreaching) since the overhead of a try-except that doesn't need to catch an exception is close to zero and the exception normally reflects the uncommon case. However, since raising and catching an exception is quite expensive, if it is a situation where average and/or worst-case performance matters more than common case performance, testing a condition first may start to appear more attractive if the preemptive check is faster than the exception handling would be.
One thing to keep in mind, though, is that some pre-emptive checks are using the moral equivalent of a try/except block under the covers (with hasattr() being the classic example of this), so the performance gain in the exceptional case actually isn't all that great. You really need to profile it to figure out which is faster.
You do need to take care that the try/except isn't covering too much though, and, depending on how obscure the exception is, potentially add a comment as to the error condition you're checking for.
As far as the original post's request goes, no. issubclass expects to be given two types. If you have an insanely polymorphic variable that can contain a wide variety of objects, only some of which are type instances, then either use isinstance to check first as you are already doing, or a try-except block to convert the TypeError to a False result (and bundle the combined test into a helper function if you're doing it a lot).