Python Tricks: Simplifying If Statements & Boolean Evaluation | by Louis Chan | Towards Data Science

Welcome to a series of short posts each with handy Python tricks that can help you become a better Python programmer. In this blog, we will look into boolean evaluation.
Let’s say we have a variable x and we would like to do something if a certain condition is met. A basic approach would be as follows:
if x == condition:    print("Conditions met!")else:    print("Conditions not met!")
With the operator ==, we are doing a boolean evaluation of whether x equals condition. But do you know that we don’t always need to explicitly call for a boolean evaluation for the if statement to work?
We all know that True and False in Python can be represented as 1 and 0 respectively as an integer. This means that instead of checking if x is 1, we can simply do the following:
x = 1# This will return Trueif x:    print("True")else:    print("False")
In fact, all integers and floats except 0 and 0.0 would return True when evaluated as a boolean. (Yes, even np.inf and np.nan are evaluated as True)
for x in range(-10, 11):    print(f"{x}: {bool(x)}") # Only 0 will be Falseimport numpy as npfor x in np.arange(-10, 11, .5):    print(f"{x}: {bool(x)}") # Only 0.0 will be Falseprint(bool(np.inf)) # Trueprint(bool(np.nan)) # True
It is quite common for functions that extract information from the input to return None if nothing can be extracted. An example of this is re.match:
import rematch = re.match(r"Goodbye", "Hello, World!")if match is None:    print("It doesn't match.")else:    print("It matches.")
However, it might be confusing at times when you have a bunch of if x is None and if x is not None etc. And this is where using boolean evaluation and sticking with a consistent approach can help:
import rematch = re.match(r"Goodbye", "Hello, World!")if match:    # this block will run if match is not None    print("It match.")else:    # this block will run if match is None    print("It doesn't match.")
Depending on your preference, you can have if match or if not match as your if statement. The key here is to stick with and not mix the two within the same codebase. Additionally, if you are using Python 3.9 or above, you can also use the Walrus operator to further simplify the code above:
import reif match := re.match(r"Goodbye", "Hello, World!"):    # this block will run if match is not None    print("It match.")else:    # this block will run if match is None    print("It doesn't match.")
Apart from int, float, and None, it is also possible to evaluate dict, set, list, tuple, and str as booleans (Note that namedtuple is not among them). The way boolean evaluation works on these iterables are with their built-in __len__ method. That is, the length of the iterable will be used as a bool. Reapplying boolean evaluation logic for numeric types, we now also know that the following special cases are the ones where iterables are evaluated as False:
print(bool(tuple())) # Falseprint(bool(dict()))  # Falseprint(bool(set()))   # Falseprint(bool(list()))  # Falseprint(bool(""))      # False
That means instead of doing:
x = [0, 1, 2, 3]if len(x) > 0:    print("The list is not empty")else:    print("The list is empty")
We can do this:
x = [0, 1, 2, 3]if x:    print("The list is not empty")else:    print("The list is empty")
Now that we know the magic of boolean evaluation for more complex data structures depends on the built-in method __len__, we can extend the knowledge to other classes. Let’s say we have a class:
class Dummy:    def __init__(self):        self.__state = False        def toggle(self):        self.__state = not self.__state        def __len__(self):        return self.__state
If we run the following scripts, we will see how the boolean evaluation of class Dummy changes:
d = Dummy()bool(d) # Falsed.toggle()bool(d) # Trued.toggle()bool(d) # False
Note that calling __len__ after changing self.__state will throw an TypeError as None cannot be cast into an int which is the type that __len__ is supposed to return.
This blog has discussed how boolean evaluation works and how it can help simplify if statements and make the codebase more consistently maintainable. As a recap, here is a list of boolean evaluation logic for some non-boolean types in Python:
int: False if 0, otherwise True
float: False if 0.0, otherwise True
dict, set, list, tuple, and str: False if length is 0, otherwise True
Custom classes: False if __len__ returns 0, otherwise True
That’s about it for this blog post! I hope you have found this useful. If you are interested in other Python tricks, I have put together a list of these short blogs for you:
Python Tricks: Flattening Lists
Python Tricks: Check Multiple Variables against Single Value
Python Tricks: How to Check Table Merging with Pandas
If you want to learn more about Python, Data Science, or Machine Learning, you may want to check out these posts:
7 Easy Ways for Improving Your Data Science Workflow
Efficient Conditional Logic on Pandas DataFrames
Memory Efficiency of Common Python Data Structures
Parallelism with Python
Essential Jupyter Extension for Data Science Set Up
Efficient Root Searching Algorithms in Python
If you would like to learn more about how to apply machine learning to trading & investing, here are some other posts that may be of interest:
Genetic Algorithm for Trading Strategy Optimization in Python
Genetic Algorithm — Stop Overfitting Trading Strategies
ANN Recommendation System for Stock Selection