LBYL vs EAFP

Chris Angelico rosuav at gmail.com
Tue Feb 5 00:19:20 EST 2013


On Tue, Feb 5, 2013 at 2:52 PM, Steven D'Aprano
<steve+comp.lang.python at pearwood.info> wrote:
> On Tue, 05 Feb 2013 10:38:41 +1100, Chris Angelico wrote:
>
>> On Tue, Feb 5, 2013 at 10:16 AM, Steven D'Aprano
>> <steve+comp.lang.python at pearwood.info> wrote:
>>> A third option is not to check x at all, and hope that it will blow up
>>> at some arbitrary place in the middle of my code rather than silently
>>> do the wrong thing. I don't like this idea because, even if it fails,
>>> it is better to fail earlier than later.
> [...]
>
>> With
>> the specific examples given, I wouldn't like to use "x + 0" as a check;
>> it seems dodgy. Firstly because it doesn't look like a data type check
>
> Strange. To me, it looks like "oh, you're testing whether x supports
> numeric addition". I suppose the hidden assumption I'm making is that if
> x supports addition, it is a kind of number. Perhaps that's an unsafe
> assumption.

If your code bombs and the exception traceback shows a line saying "x
+ 0", I'm going to wonder if it's a massive bug... or, worse, if
you're expecting x.__add__() to have stupid side effects ("yeah,
adding 0 to x turns x into a float, but subtracting 0 from it forces
it to be an int").

>> (though a comment can help with that), and secondly because something
>> might very well support having a number added to it while definitely not
>> itself being a number - eg something along the lines of a database
>> cursor.
>
> But surely duck-typing tells us that if database cursors support the same
> sort of operations that numbers support, we should therefore treat them
> as a kind of number?

Depends what operations you mean. It's not uncommon for a
cursor/iterator object to support "x+=1" to move to the next
row/element/whatever; if your result set is maintained elsewhere, you
could cheaply support "x + 4" to create a new iterator that's four
rows further along. But in all other respects, it's not a number. You
can't multiply an iterator by 2, for instance.

> My library will not try to prevent the caller taking the average of (say)
> a dozen eggs and 10 miles. I'm not sure that it should try to prevent the
> caller from trying to take the average between two database cursors.

Well, sure... if your code is so simple and trivial, and if the
cursors support "x - y" to get the number of rows between them. But in
that case, go for true EAFP and eschew error checking altogether.

ChrisA



More information about the Python-list mailing list