← str · 🏠 Домой · Область видимости →
Коротко. bool — подкласс int. True — это единица, False — ноль,
и они ведут себя как числа везде, где числа уместны.
issubclass(bool, int) # True
isinstance(True, int) # True
bool.__mro__ # (<class 'bool'>, <class 'int'>, <class 'object'>)
True == 1 # True
True + True # 2
sum([True, True, False]) # 2Это самый частый вопрос про bool на собеседовании, и у него есть практическое
следствие: подсчитать количество подходящих элементов можно просто суммой
условий — sum(x > 0 for x in data).
Подвох. Раз True == 1 и хеши совпадают, то в словаре это один и тот же
ключ:
{1: 'a'}[True] # 'a'
{1: 'a', True: 'b'} # {1: 'b'} — ключ один, значение перезаписаноТот же эффект в set: {1, True} — это множество из одного элемента.
Глубже. Исторически bool появился только в Python 2.3 (PEP 285), и
наследование от int выбрали ради обратной совместимости — код, который уже
использовал 1/0 как истину и ложь, должен был продолжать работать.
Подвох. Дальше bool унаследовать нельзя — class MyBool(bool): pass
падает с TypeError: type 'bool' is not an acceptable base type. CPython
намеренно запрещает наследование от bool, чтобы сохранить гарантию, что
существуют ровно два экземпляра — True и False.
Коротко. Не True/False, а один из операндов. Оба оператора ленивые:
вычисляют правую часть, только если это нужно для результата.
'x' and 'y' # 'y' — оба истинны, вернулся последний
'' or 'def' # 'def' — левый ложен, вернулся правый
0 or [] # [] — оба ложны, вернулся последнийa and b— еслиaложен, возвращаетa, иначеb.a or b— еслиaистинен, возвращаетa, иначеb.not a— единственный из трёх, кто всегда возвращает настоящийbool.
Отсюда идиома «значение по умолчанию»: name = user_input or "аноним".
Подвох. У этой идиомы есть ловушка: она подменит любое ложное значение, а не
только пустое. count = value or 10 превратит переданный 0 в 10. Когда важно
отличить «не передали» от «передали ложное», нужна явная проверка
if value is None.
Глубже. Ленивость — не оптимизация, а часть семантики: на неё опираются
конструкции вроде if obj is not None and obj.field, где правая часть упадёт,
если левая ложна. Подробнее о том, что считается истинным, — в разделе
Truthy and Falsy.