Implicit conversion to boolean in if and while statements

Steven D'Aprano steve+comp.lang.python at
Mon Jul 16 04:13:56 CEST 2012

On Sun, 15 Jul 2012 10:19:16 -0600, Ian Kelly wrote:

> On Sun, Jul 15, 2012 at 4:56 AM, Steven D'Aprano
> <steve+comp.lang.python at> wrote:
>> (For the record, I can only think of one trap for the unwary: time
>> objects are false at *exactly* midnight.)
> Ugh, that's irritating.  I can't think of any scenario where I would
> ever want the semantics "if timeval (is not midnight):".

Yes, it is a genuine gotcha. Time values are numbers, and zero is falsey, 
so midnight is falsey even though it shouldn't be.

There's no good solution here, since we have a conflict between treating 
time values as time values ("midnight is nothing special") and as numbers 
("midnight == 0 which is falsey"). The only "solution" is to throw out 
duck-typing of boolean values, which is tossing the baby out with the 
bathwater -- bool duck-typing works fine for everything else.

> This
> reinforces the point that if you only want to test whether you have
> None, you should use "is not None" rather than relying on __bool__.

Often you should, but I didn't mention anything about testing for None. 
Testing objects in a boolean context is more than just testing for None.

I have just written a bunch of code with about two dozen examples similar 
to this:

for item in (seq or []):

iterates over seq if it is non-empty, or the empty list. Writing it like 
this would be more painful, more complex, less readable and less 

if seq is not None:
    for item in seq:

not to mention completely unnecessary if you have already checked that 
seq is either None or a sequence, and not some other arbitrary value.

(If seq really could be any type at all, then an explicit identity test 
against None is required.)

One of my favourites:

value = (dict or {}).get('key')

instead of:

value = None if dict is None else dict.get('key')


More information about the Python-list mailing list