Relying on the behaviour of empty container in conditional statements

Steven D'Aprano steve at REMOVETHIScyber.com.au
Tue Jul 11 08:56:52 EDT 2006


On Tue, 11 Jul 2006 04:52:42 -0700, horizon5 wrote:

> Hi,
> 
> my collegues and I recently held a coding style review.
> All of the code we produced is used in house on a commerical project.
> One of the minor issues I raised was the common idiom of specifing:
> 
> <pre>
> if len(x) > 0:
>     do_something()
> </pre>
> Instead of using the language-defined bahviour, as stated by PEP8:
> 
> <pre>
>     - For sequences, (strings, lists, tuples), use the fact that empty
>       sequences are false.
> 
>       Yes: if not seq:
>            if seq:
> 
>       No: if len(seq)
>           if not len(seq)
> </pre>
> 
> Without wishing to start a flame war, what are other's opinions on
> this, is using "len" safer? If so why?

What do you mean by "safer"? What sort of bad consequences are you trying
to avoid? What sort of errors do your colleagues think writing "if seq"
encourages?

Just waving hands in the air and saying "Doing foo is safer" is
meaningless. Safer than what? What are the costs and benefits of doing
foo? What are the consequences of failure?


 
> Arguments that have been presented for using <code>len(x) > 0</code> to
> test emptiness of a container include:
>   - It's safer

On the contrary, the longer test isn't safer, it is more dangerous because
there is a whole family of potential bugs that can occur when using that
idiom, but which can't occur in the shorter test.

For example, there are typos like writing "len(x) < 0" by mistake. (Or,
for that matter, len(x) > 9.)

Do you have a function ln defined in the current scope? Then you better
hope that you don't mistype len(x) as ln(x).

Sure, the chances of these sorts of errors are small -- but not zero.
Write enough tests, and you will surely make them. But they are impossible
to make in the shorter "if x" idiom.


>   - Not relying on weird behaviour of the language

There is nothing weird about it. Languages which don't accept arbitrary
objects as truth values are weird. Every object should know whether or not
it is nonempty/true or empty/false.


>   - Explicit is better than implicit (as stated by 'this' module, Zen
> of Python)

"if x:" is explicit. It is explicitly asking, does x evaluate as true in a
Boolean context or as false?

In an object-oriented framework, it is bad practice for the developer to
concern himself with what makes an object true or false. Instead, you
should simply ask the object, are you true?

What happens when you decide that using a list (or tuple) for x is not the
right way to solve your problem? You change it to something like, say, a
binary tree. Now len(x) > 0 is undefined, because trees don't have a
length. You could ask if height(x) > 0 but calculating the height of a
tree is, in general, expensive. Better to simply ask the tree if it is
true or false.

Or, you subclass list to use a sentinel value. There may be some good
reason for not wanting to redefine the __len__ method of the subclass, so
the length of the subclassed list is ALWAYS positive, never zero. If you
have peppered your code with tests like "if len(x) > 0", you're in
trouble. You're in even greater trouble if some of those tests might be
called by *either* regular lists or by the new subclass. Now you have to
start turning your tests into something awful like this:

if (x.__class__ == ListWithSentinal and len(x) > 1) or len(x) > 0:

But if the subclass redefines the __nonzero__ method, and you use "if x"
as your test, you're done. One change, in one place, compared to
potentially hundreds of changes scattered all over your code.


There are times where your code is constrained by your data-type, e.g.
tests like "if len(x) > 5:" or similar. But they are comparatively rare.
Why force simple true/false tests into that idiom?


> My own feeling is that I am willing to work with the behaviours defined
> by Python, and treat the use of len in these cases as excessive
> duplication (this is however, quite a minor point i agree).
> 
> Note that I have much more experience with the language (6-7 years),
> whilst the majority of my collegues have about 1-2 years experience.

Sounds like they are still programming C or Java in Python.

Good luck teaching these young whipper-snappers. *wink*



-- 
Steven.




More information about the Python-list mailing list