class with __len__ member fools boolean usage "if x:" ; bad coding style?

John Roth newsgroups at jhrothjr.com
Fri Jun 25 20:55:37 EDT 2004


"george young" <gry at ll.mit.edu> wrote in message
news:78b6a744.0406250737.310f31da at posting.google.com...
> [Python 2.3.3, x86 linux]
> I had developed the habit of using the neat python form:
>    if someinstance:
>       someinstance.memb()
>
> because it seems cleaner than "if someinstance is not None".
> {please no flames about "is not None" vs. "!= None" ...}
>
> This seemed like a good idea at the time :().  Twice, recently,
> however, as my
> app grew, I thought, hmm... it would make things clearer if I gave
> this container class a __len__ member and maybe a __getitem__. Great,
> code looks
> nicer now... crash,crash, many expletives deleted...
>
> Its great to be able to say containerinstance[seq] instead of
> containerinstance.steps[seq], but I've also changed the semantics of
> (containerinstance) in a boolean context.  My app breaks only in the
> seldom case that the container is empty.
>
> Obviously I know how to fix the code, but I'm wondering if this isn't
> a message
> that "if containerinstance:" is not a good coding practice.

Almost. The message is that testing for None, however
you're doing it, is a Code Smell in the sense defined in
the Refactoring book. If some attribute is supposed to have
a Foo object, then it should have a Foo or a subclass of
Foo, not None.

Sometimes there's no way around it, but whenever you find
yourself testing for None, consider using a Null Object instead.
A Null Object is a subclass of the normal object you would
be expecting, but one that has methods and attributes that
handle the exceptional case cleanly.

Of course, there are a couple of very pretty idioms for
handling optional parameters that depend on tests for None,
but they're definitely special cases, and they also break if the
real parameter can be False.

John Roth





More information about the Python-list mailing list