Search notes:

Python: evaluating objects in boolean context

Every object can be evaluated in a boolean context, such as if or while statements.
The following exmaples demonstrate the rules that determine if an object is considered to be True or False.

Objects without __bool__() and __len__() are True

An object that has neither a __bool__ nor a __len__ method is considered to be true.
class no_bool_no_len:
    pass

always_true = no_bool_no_len()

if always_true  :
   print("It's true")
else:
   print("Well, it's false")
Github repository about-Python, path: /objects/evaluating-in-boolean-context/no-bool-no-len.py

__bool__() determines the truthness of an object

If the object has a __bool__() method is False the returned value of __bool__() determines the truthness of the object.
class with_bool:

    def __init__(self, cntTrue):
        self.cntTrue = cntTrue

    def __bool__(self):

        print("__bool__: cntTrue = " + str(self.cntTrue))

        self.cntTrue -= 1
        return self.cntTrue >= 0


W = with_bool(4)


while W:
    print("Still in loop")

print("Loop exited")
#
#  __bool__: cntTrue = 4
#  Still in loop
#  __bool__: cntTrue = 3
#  Still in loop
#  __bool__: cntTrue = 2
#  Still in loop
#  __bool__: cntTrue = 1
#  Still in loop
#  __bool__: cntTrue = 0
#  Loop exited
Github repository about-Python, path: /objects/evaluating-in-boolean-context/with-bool.py
Note that Python expects __bool__() to return a bool, otherwise, it throws a TypeError exception (TypeError: __bool__ should return bool, returned …).

__len__() is tried if __bool__() is missing

If an object does not have a __bool__() method, but does have a __len__() method, the returned value determines the Truthness of an object. If the returned value is 0, the object is False, otherwise, it is True.
#!/usr/bin/python3

class with_len:
    def __init__(self, cntTrue):
        self.cntTrue = cntTrue

    def __len__(self):

        print("__len__: cntTrue = " + str(self.cntTrue))

        self.cntTrue -= 1
        return self.cntTrue



L = with_len(4)


while L:
    print("Still in loop")

print("Loop exited")
Github repository about-Python, path: /objects/evaluating-in-boolean-context/with-len.py
Note that Python does not expect __len__() to return an int.

__bool__() takes precedence over __len__()

When evaluated in a boolean context, __bool__() takes precedence over __len__(), that is: __len__() is not even called.
#!/usr/bin/python3

class with_bool_an_len:
    def __init__(self, cntTrue):
        self.cntTrue = cntTrue

    def __bool__(self):

        print("__bool__: cntTrue = " + str(self.cntTrue))

        self.cntTrue -= 1
        return self.cntTrue >= 0

    def __len__(self):

        print("__len__: cntTrue = " + str(self.cntTrue))

        self.cntTrue -= 1
        return self.cntTrue >= 0 



L = with_bool_an_len(1)


print("Going to loop")
while L:
    print("Still in loop")

print("Loop exited")
#
#  Going to loop
#  __bool__: cntTrue = 1
#  Still in loop
#  __bool__: cntTrue = 0
#  Loop exited
Github repository about-Python, path: /objects/evaluating-in-boolean-context/with-bool-and-len.py

See also

Beware of None in while X := next(I)

Index