Skip to Content
Course content

50: Truthy and Falsy Values in Conditions

Click on the "Edit" button in the top corner of the screen to edit your slide content.

I've spent a lot of time reviewing PRs from developers moving to Python from languages like Java or C#. One of the most common habits I see is a tendency to be overly explicit when checking if a collection has items or if a string contains text. It's not "wrong"—the code works—but it's noisy. It's the programming equivalent of saying "I am currently in the state of being hungry" instead of just saying "I'm hungry."

The habit of being too explicit

Imagine you're writing a function to process a list of tags for a blog post. A newcomer to Python will often write a check like this:

def process_tags(tags):
    if len(tags) > 0:
        print(f"Processing {len(tags)} tags...")
    else:
        print("No tags to process.")

Now, there is absolutely nothing logically wrong with len(tags) > 0. It's clear and it's precise. But in Python, this is considered unidiomatic. You're asking Python to calculate the length of the list, then asking it to compare that integer to zero, and finally returning a boolean. It's a few extra steps that don't add any actual value to the logic.

Letting Python do the heavy lifting

In Python, every object has an inherent "truthiness." Instead of checking the length or comparing a value to an empty state, you can just put the object itself in the condition. An empty list, an empty string, the number 0, None, and empty dictionaries or sets are all evaluated as False in a boolean context. Everything else is generally True.

Here is how I would write that same tag processor:

def process_tags(tags):
    if tags:
        print(f"Processing {len(tags)} tags...")
    else:
        print("No tags to process.")

By saying if tags:, you're essentially asking: "Is this list non-empty?" It's cleaner, it's faster to read, and it's the way the language was designed to be used. I apply this same logic to strings—if username: is far more elegant than if username != "":.

When the shortcut bites you

Now, here is the part where you have to be careful. Truthiness is a powerful tool, but it's a blunt instrument. Because 0 is falsy, you can run into trouble if 0 is actually a valid piece of data that you need to distinguish from None or an empty value.

Consider a function that updates a user's account balance. If you write if balance:, and the user's balance is exactly 0, Python will treat that as False. If your logic was "if the balance exists, do X," you've just accidentally skipped the logic for every user who is broke.

# The Dangerous Way
def update_balance(balance):
    if not balance:
        print("No balance recorded!") # This triggers if balance is 0 OR None

# The Precise Way
def update_balance_fixed(balance):
    if balance is None:
        print("No balance recorded!") # This ONLY triggers if it's actually None

The rule of thumb I follow is this: use truthiness for collections (lists, strings, dicts) because "empty" is almost always what you're checking for. But when dealing with numbers or optional objects that could be None, be explicit. Use is None or == 0. Mixing these up is one of the most common sources of subtle bugs in Python scripts.




📋 Practical Task

Refactoring the User Profile Validator

You've been handed a piece of legacy code that validates user profile data before saving it to a database. The current implementation is clunky and uses "non-Pythonic" checks. Your task is to refactor the validate_profile function to use truthy and falsy values where appropriate, while ensuring that the age check remains explicit (since an age of 0 might be valid for an infant, but None means the data is missing).

def validate_profile(username, bio, age, interests):
    # Refactor the following checks to be more Pythonic
    if username != "":
        print("Username is valid.")
    else:
        print("Username is required.")

    if len(bio) > 0:
        print("Bio is provided.")
    else:
        print("Bio is empty.")

    # KEEP THIS EXPLICIT: We need to know if age is None, 
    # not if it is 0.
    if age is not None:
        print("Age is provided.")
    else:
        print("Age is missing.")

    if len(interests) != 0:
        print("Interests are listed.")
    else:
        print("No interests listed.")

# Test cases
validate_profile("coding_wizard", "I love Python!", 25, ["coding", "reading"])
validate_profile("", "", None, [])

Goal: Replace the username, bio, and interests checks with implicit boolean evaluations while leaving the age check exactly as it is.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.