EAFP gone wrong
Matthew Barnett
mrabarnett at mrabarnett.plus.com
Wed Feb 10 00:49:25 CET 2010
Arnaud Delobelle wrote:
> Hi all,
>
> Hi have a set of classes that represent mathematical objects which can
> be represented as a string using a 'latex' method (after Knuth's famous
> typesetting system). As I want to be able to typeset some builtin types as
> well, I have a generic function, latex(), as follows:
>
> def latex(val):
> try:
> return val.latex()
> except AttributeError:
> if isinstance(val, (tuple, list)):
> return ", ".join(map(latex, val))
> elif isinstance(val, dict):
> return ", ".join(
> "%s=%s" % (latex(k), latex(v))
> for k, v in sorted(val.iteritems())
> )
> else:
> return str(val)
>
> It's EAFP and I have used this for a while with no problem. Recently I
> added a new class for 'n choose r' objects, as follows:
>
> class Choose(Expression):
> def __init__(self, n, r):
> self.subexprs = n, r
> self.n = n
> self.r = r
> def calc(self, ns=None, calc=calc):
> return choose(calc(self.n, ns), calc(self.r, ns))
> def latex(self):
> return "{%s \\choose %s}" % (latex(self.n), latex(self.k))
>
> When I create a Choose object and try to get its latex representation,
> this happens:
>
>>>> c = Choose(5, 3)
>>>> latex(c)
> '<qmm.maths.expressions.Choose object at 0x17c92d0>'
>
> This puzzled me for a bit: why is it not trying to use the latex()
> method of the Choose object? I read and reread the definition of the
> latex() method for a while until I found that there was a typo. Where
> it says:
>
> latex(self.k)
>
> it should say:
>
> latex(self.r)
>
> Thus it triggers an AttributeError, which is exactly the kind of
> exception that I am catching in the latex() function after trying
> val.latex(). (Of course I could have caught this by calling c.latex()
> directly but it's such a short method definition that I couldn't imagine
> missing the typo!).
>
> This means that EAFP made me hide a typo which would have been obviously
> detected had I LBYLed, i.e. instead of
>
> try:
> return val.latex()
> except AttributeError:
> ...
>
> do
>
> if hasattr(val, 'latex'):
> return val.latex()
> else:
> ...
>
>
> So was it wrong to say it's EAFP in this case? Should I have known to
> LBYL from the start? How do you decide which one to use? Up to now, I
> thought it was more or less a matter of taste but now this makes me
> think that at least LBYL is better than catching AttributeError.
>
> Thanks for any guidance.
>
In addition to the other replies, you should've tested the Choose class. :-)
More information about the Python-list
mailing list