Python Woes – Boolean Casting

Python Logo

The C language has the strange feature that it does not really distinguish between integer, pointers and booleans, True is any integer value different from zero and False is zero. Nowadays it is considered bad form to (over)use that feature.

Python has a feature which is similar: most build-in types evaluate to a boolean, like in C, a-non zero number is considered true. The feature extends to collections: any non empty collection is true, an empty collection is false. Any class can implement this behaviour by implementing the __nonzero__ or __len__ if it is a collection. It is considered pythonic to use the implicit boolean evaluation instead of checking if an integer is zero or a collection is empty.

Another important aspect of Python is duck typing, i.e. having code that does not make strong assumptions on what types it gets as an input, if it quack like a duck, treat it as a duck. This typically means that a function that takes in a collection does not need to worry about which type of collection it gets: it can be a tuple, a list, a set. All built-in collection have a constructor that take another collection, so you can freely convert between the collections.

Python also has object that behave like collections: files, iterators, generators. You can use them instead of a collection in a loop, with an in statement and of course cast them into a list. There is one hitch: while that casting preserves the boolean property for real collections, it does not for these quasi-collections.

e = itertools.repeat(0, 0)
bool(e) → True
bool(list(e)) → False

The same thing happens with an existing, empty file. This is pretty annoying because this means that the boolean operator does not return the answer to the question does this thing contain elements, instead it answer a more convoluted question is this thing a pseudo collection or if it is a real collection, does it contain any elements, so basically, to know what this operator means, you need to know its type, which goes against the whole idea of duck typing. This goes against the intuition that the boolean property represents some high-level property…

It’s worth noting that you have a similar problem with numbers:

bool(1) → True
bool(int(True)) → True
bool(int(False)) → False
bool(0.5) → True
bool(int(0.5)) → False

2 thoughts on “Python Woes – Boolean Casting”

Leave a Reply