0

This is more of a philosophical question.

In python, bool([]) evaluates to False. On the other hand, consider the following:

from dataclasses import dataclass


@dataclass
class Lists:
    items: list[str]
    other_items: list[str]


assert bool(Lists(items=[], other_items=[]))

The above snippet doesn't raise AssertionError.

Why is that?

I encountered a use-case where it seems to make sense to deduce an object's truth value by aggregating the truth values of its attributes.

Are there any caveats to keep in mind before doing so?

(I'm talking about data classes, like dataclass or pydantic.BaseModel)

6
  • 3
    An object always has a "true" value. Python doesn't/can't look inside it. You can override this behavior, if you want, using the special __bool__ method. Commented Mar 6, 2024 at 6:36
  • @TimRoberts what do you mean by "an object always has a true value"? Objects like None, [], and 0 has the truth value of False. I know the technicalities of __bool__ - my question is more about why libraries like pydantic and dataclasses chose to implement it the way they did. Commented Mar 6, 2024 at 6:49
  • 1
    @TimRoberts I think we have to be careful when talking about "objects" in this context. For example, a string (str) is an "object" that doesn't implement __bool__ and yet is falsey if it represents an empty string Commented Mar 6, 2024 at 7:54
  • 1
    @CtrlZ Strings have a length: By default, an object is considered true unless its class defines either a __bool__() method that returns False or a __len__() method that returns zero, when called with the object. docs.python.org/3/library/stdtypes.html#truth-value-testing Commented Mar 6, 2024 at 8:16
  • 1
    The "why" is because dataclasses would have to make some huge assumptions about your design. There is precedence for this behavior -- a list that contains two empty lists is not "False". A dict with an empty key and value is not "False". This is why you have the __bool__ option. Commented Mar 6, 2024 at 18:49

1 Answer 1

2

An instance of a Python class is always truthy unless it implements __bool__() or __len__()

Simple example:

class FOO():
    def __init__(self, x:str|None=None):
        self._x = x
    def __bool__(self) -> bool:
        return self._x is not None


class BAR:
    def __init__(self, x:str|None=None):
        self._x = x
    def __len__(self) -> int:
        return 0 if self._x is None else len(self._x)

print(bool(FOO()))
print(bool(FOO("hello")))
print(bool(BAR()))
print(bool(BAR("hello")))

Output:

False
True
False
True
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.