LBYL vs EAFP
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Mon Feb 4 23:52:18 EST 2013
On Mon, 04 Feb 2013 16:46:11 -0700, Ian Kelly wrote:
> Presumably if the operation requires
> a number, then it will at some point perform some kind of numerical
> manipulation that will raise a TypeError if one is not passed. If the
> operation succeeds, then the object supported all the operations you
> asked of it, so in what sense would the program be doing the wrong
> thing?
It might not support *all* the operations. Consider a toy function like
this:
def toy(x): # Don't try this at home!
return x*10000000000 + 1
If you pass a non-empty list, Python will:
- try to allocate a chunk of memory of at least 4 GB (estimated), which
may cause quite a bit of thrashing;
- if somehow this succeeds, then it will create a list and populate it
with rather a lot of duplicated references;
- at which point it will then try to add a list to an int, and raise an
exception;
- and then deallocate a huge list, causing more thrashing.
So there are consequences to allowing exceptions to occur in arbitrary
places.
There's also the principle that it is best to raise an exception as early
as possible. It's easier to track down errors at the point they are
introduced than long afterwards.
And finally, even worse than exceptions are silent failures of semantics:
code that does the wrong thing rather than fail loudly and safely. Just
because the code doesn't fail, doesn't mean it has worked, and an
exception is much better than a silent failure. You seem to be making the
classic mistake of thinking that exceptions are something to avoid:
"I find it amusing when novice programmers believe their main job is
preventing programs from crashing. [...] More experienced programmers
realize that correct code is great, code that crashes could use
improvement, but incorrect code that doesn’t crash is a horrible
nightmare." -- Chris Smith
http://cdsmith.wordpress.com/2011/01/09/an-old-article-i-wrote/
Duck-typing is not a panacea, and it too has failure modes. The usual
example is, suppose you have a graphics application that expects an
object with a "draw" method:
pencil.draw()
paintbrush.draw()
crayon.draw()
six_shooter.draw() # bang, you've just shot yourself in the foot
So I lean very strongly to some sort of explicit check ahead of time. I'm
just not sure *what sort* of explicit check.
--
Steven
More information about the Python-list
mailing list