Функция bool в Python и проверка истинности
Функция bool() в Python превращает любое значение в логическое True или False по правилам проверки истинности. Ниже разобраны синтаксис функции, полный список ложных значений, неявная проверка в условиях, связь типа bool с int, метод __bool__ для своих классов и типичные ошибки новичков.

Содержание статьи
Синтаксис и возвращаемое значение
Функция принимает один необязательный аргумент и всегда возвращает один из двух объектов: True или False. Вызов без аргумента дает False. Начиная с Python 3.7 аргумент передается только по позиции, запись bool(x=1) вызовет TypeError.
print(bool()) # False
print(bool(42)) # True
print(bool(0)) # False
print(bool("текст")) # True
print(bool("")) # False
print(type(bool(1))) # <class 'bool'>bool - это одновременно встроенный тип данных и функция-конструктор этого типа. Новых экземпляров она не создает: True и False существуют в единственном экземпляре, поэтому их можно сравнивать через is.
Какие значения считаются ложными
Ложных значений в Python немного, их проще запомнить, чем истинные. Все, чего нет в таблице, считается истинным.
| Категория | Ложные значения |
|---|---|
| Константы | None, False |
| Нули любых числовых типов | 0, 0.0, 0j, Decimal(0), Fraction(0, 1) |
| Пустые последовательности | "", [], (), range(0), b"" |
| Пустые коллекции | {}, set(), frozenset() |
| Свои объекты | Если __bool__() вернул False или __len__() вернул 0 |
На практике путаются в значениях, которые выглядят пустыми или нулевыми, но таковыми не являются:
print(bool([0])) # True, список не пустой
print(bool("0")) # True, строка из одного символа
print(bool("False")) # True, непустая строка
print(bool(" ")) # True, пробел тоже символ
print(bool(float("nan"))) # True, nan не равен нулю
print(bool([[]])) # True, внутри есть элементОсобенно часто ошибка возникает при обработке ввода. Функция input() всегда возвращает строку, и bool("0") или bool("нет") дадут True. Ответ пользователя нужно сравнивать со строкой явно: answer.lower() in ("да", "yes").
Неявная проверка в if и while
Вызывать bool() вручную приходится редко. Инструкции if, while, операторы and, or, not сами проверяют истинность любого объекта точно по тем же правилам. Поэтому принято писать коротко, без сравнений с пустыми значениями.
items = []
if not items: # вместо if len(items) == 0
print("Список пуст")
name = "Анна"
if name: # вместо if name != ""
print(f"Привет, {name}")У короткой записи есть ловушка. Если переменная может законно быть нулем или пустой строкой, проверка if value: спутает их с отсутствием значения. Когда нужно отличить None от остальных значений, сравнивайте через is None. Подробнее об условиях в статье условия в Python.
def apply_discount(price, discount=None):
if discount is None: # 0 - допустимая скидка
discount = 5
return price * (100 - discount) / 100
print(apply_discount(1000, 0)) # 1000.0, а с if not discount было бы 950.0Тип bool как подкласс int
Тип bool унаследован от int: True ведет себя как 1, False как 0. Поэтому логические значения можно складывать и использовать как индексы. Проверка isinstance(True, int) возвращает True, это стоит учитывать при проверке типов через isinstance.
print(True + True) # 2
print(isinstance(True, int)) # True
scores = [5, 3, 4, 2, 5]
passed = sum(s >= 4 for s in scores)
print(passed) # 3, количество True
print(["нет", "да"][10 > 3]) # даПодсчет через sum() по условию - распространенный прием: каждое сравнение дает True или False, а сумма равна количеству выполненных условий. Похожая логика лежит в основе функций all() и any(), которые проверяют истинность сразу всех или хотя бы одного элемента.
Истинность собственных классов
По умолчанию любой объект пользовательского класса истинен. Это поведение меняют два специальных метода. Сначала Python ищет __bool__(), который должен вернуть True или False. Если его нет, вызывается __len__(), и объект ложен при длине 0.
class Cart:
def __init__(self):
self.items = []
def __len__(self):
return len(self.items)
class Account:
def __init__(self, balance):
self.balance = balance
def __bool__(self):
return self.balance > 0
print(bool(Cart())) # False, корзина пуста
print(bool(Account(150))) # True
print(bool(Account(0))) # FalseЕсли __bool__() вернет не логическое значение, а, например, число 1, Python выбросит TypeError. Описание правил есть в документации Python.
Операторы and, or и not
Оператор not всегда возвращает True или False. Операторы and и or устроены иначе: они возвращают один из операндов, а не результат bool(). or отдает первый истинный операнд или последний, если истинных нет. and отдает первый ложный операнд или последний, если все истинны.
print(not []) # True
print("" or "гость") # гость
print(0 and 10) # 0
print(5 and 10) # 10
name = input().strip() or "Аноним" # значение по умолчаниюПрием с or для значения по умолчанию удобен, но с ним та же ловушка, что и с if: ноль и пустая строка тоже будут заменены. Если результат нужен строго логического типа, оберните выражение в bool(): bool(a and b).
Частые вопросы
Короткие ответы на вопросы о функции bool().
Как преобразовать строку "False" в False?
Функция bool() для этого не подходит, любая непустая строка дает True. Сравните строку явно: value = text.strip().lower() == "true". Для разбора ответов вроде "да" и "нет" заведите множество допустимых вариантов.
Чем отличается проверка if x от if x is not None?
Первая отбрасывает все ложные значения: None, 0, пустую строку, пустой список. Вторая отбрасывает только None. Если 0 или пустая строка являются корректными данными, нужна вторая форма.
Можно ли сравнивать с True через ==?
Технически можно, но это лишнее: if flag == True равносильно if flag для логических значений и дает неожиданный результат для других, ведь 2 == True ложно, хотя число 2 истинно. Руководство PEP 8 рекомендует писать просто if flag:.
Почему bool является подклассом int?
Так сложилось исторически: тип bool появился в Python 2.3, когда в коде уже повсеместно использовались 1 и 0 как логические значения. Наследование от int сохранило совместимость со старым кодом.