ZetCode

Python __bool__ Method

Last modified April 8, 2025

This comprehensive guide explores Python's __bool__ method, the special method that defines an object's truth value. We'll cover basic usage, truthiness rules, practical examples, and common patterns.

Basic Definitions

The __bool__ method is called to implement truth value testing and the built-in bool() function. It should return True or False.

When __bool__ is not defined, Python falls back to __len__. If neither is defined, objects are considered True by default. This method is crucial for control flow statements.

Basic __bool__ Implementation

Here's a simple example showing how to implement __bool__ to control an object's truthiness. The method must return a boolean value.

basic_bool.py
class Account:
    def __init__(self, balance):
        self.balance = balance
    
    def __bool__(self):
        return self.balance > 0

account1 = Account(100)
account2 = Account(-50)

print(bool(account1))  # True
print(bool(account2))  # False

if account1:
    print("Account has funds")

This example defines an Account class where an account is considered truthy if its balance is positive. The __bool__ method encapsulates this business logic.

The method is automatically called when the object is used in a boolean context, like if statements or with the bool() function.

__bool__ with __len__ Fallback

When __bool__ is not defined, Python uses __len__ as a fallback. This example shows both methods working together.

bool_len.py
class ShoppingCart:
    def __init__(self, items):
        self.items = items
    
    def __len__(self):
        return len(self.items)
    
    def __bool__(self):
        return any(item.price > 0 for item in self.items)

class Item:
    def __init__(self, price):
        self.price = price

cart1 = ShoppingCart([Item(10), Item(20)])
cart2 = ShoppingCart([Item(0), Item(0)])

print(bool(cart1))  # True (__bool__ returns True)
print(bool(cart2))  # False (__bool__ returns False)
print(bool(ShoppingCart([])))  # False (__len__ returns 0)

This example shows that __bool__ takes precedence over __len__. For empty carts, Python falls back to __len__ when __bool__ isn't defined.

The cart is considered truthy only if it contains at least one item with a positive price, demonstrating custom truthiness logic.

Truthiness in Data Validation

__bool__ can be used to implement validation logic, making objects usable in boolean contexts to check their validity.

validation.py
class UserProfile:
    def __init__(self, name, email):
        self.name = name
        self.email = email
        self._validate()
    
    def _validate(self):
        self.is_valid = (
            isinstance(self.name, str) and 
            '@' in self.email
        )
    
    def __bool__(self):
        return self.is_valid

valid_user = UserProfile("Alice", "alice@example.com")
invalid_user = UserProfile(123, "bobexample.com")

print(bool(valid_user))    # True
print(bool(invalid_user))  # False

if not invalid_user:
    print("Profile is invalid")

This example uses __bool__ to expose validation status. The method returns the internal is_valid flag set during initialization.

This pattern is useful when you want objects to self-report their validity in a natural way through boolean testing.

Custom Container Truthiness

For container-like objects, __bool__ can provide meaningful truthiness based on container state, similar to built-in containers.

container.py
class Playlist:
    def __init__(self, songs):
        self.songs = list(songs)
    
    def __bool__(self):
        return len(self.songs) > 0 and any(
            song.duration > 0 for song in self.songs
        )
    
    def __len__(self):
        return len(self.songs)

class Song:
    def __init__(self, duration):
        self.duration = duration

empty_playlist = Playlist([])
playlist_with_silent_tracks = Playlist([Song(0), Song(0)])
valid_playlist = Playlist([Song(180), Song(240)])

print(bool(empty_playlist))               # False
print(bool(playlist_with_silent_tracks))  # False
print(bool(valid_playlist))               # True

This Playlist class is only considered truthy if it contains songs with positive duration. It combines length check with content validation.

The implementation follows Python's principle that empty containers are falsey, but extends it with domain-specific logic about what constitutes a "valid" playlist.

__bool__ in Stateful Objects

For stateful objects, __bool__ can reflect the current state, making state checks more intuitive and Pythonic.

stateful.py
class TrafficLight:
    def __init__(self):
        self._state = 'red'
    
    def change(self):
        if self._state == 'red':
            self._state = 'green'
        elif self._state == 'green':
            self._state = 'yellow'
        else:
            self._state = 'red'
    
    def __bool__(self):
        return self._state == 'green'

light = TrafficLight()
print(bool(light))  # False

light.change()
print(bool(light))  # True

light.change()
print(bool(light))  # False

This traffic light implementation uses __bool__ to indicate whether the light is green. The boolean value changes as the light's state changes.

This pattern makes code more readable when checking object state, as if light: clearly expresses the intent to check for the green state.

Best Practices

Source References

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all Python tutorials.