Ответ 1
Вы смешиваете две концепции: тестирование равенства и тестирование истины. Они не совпадают с Python.
Я думаю, что вызвало вопрос, что Python делает неявное кастинг, когда вы делаете if something
(он передает что-то bool
), но не делать неявное литье, когда вы делаете something1 == something2
.
Модель данных Pythons на самом деле объясняет, как эти операции выполняются:
Проверка правды
- Он начинается с проверки того, реализует ли объект метод
__bool__
, и если он использует это, возвращается возвращаемое логическое значение. - Если он не определяет метод
__bool__
, он смотрит на метод__len__
. Если он будет реализован, он будет использовать результатlen(obj) != 0
. - Если он не имеет ни объект, который считается
True
.
Для целых чисел метод __bool__
возвращает True
, за исключением случаев, когда целочисленное значение 0
(тогда оно False
).
Объект Ellipsis (...
является объектом Ellipsis), с другой стороны не реализует __bool__
или __len__
, поэтому он всегда True
.
Проверка равенства
Тестирование равенства использует метод __eq__
аргументов как. Это скорее цепочка операций:
- Он проверяет, реализует ли первый операнд
__eq__
, когда второй операнд передается как аргумент. - Если это не так, он проверяет, реализует ли второй операнд
__eq__
, когда первый операнд передается как аргумент. - Если это не так, то Python проверяет идентификатор объекта (если они являются одним и тем же объектом - похожим на сравнение указателей на языках C)
Порядок этих операций может варьироваться. 1
Для встроенных типов Python эти операции явно реализованы. Например int
egers реализуют __eq__
, но CHECK_BINOP
гарантирует, что он возвращает NotImplemented
, если другой не является int
eger.
Объект Ellipsis
вообще не реализует __eq__
.
Поэтому, когда вы сравниваете целые числа и Ellipsis Python всегда будет возвращаться к идентификатору объекта, и поэтому он всегда будет возвращать False
.
С другой стороны, bool
eans являются подклассом int
egers, поэтому они фактически сравниваются с int
(иначе они являются int
). Булевы реализованы как 1
(True
) и 0
(False
). Поэтому они сравнивают равные:
>>> 1 == True
True
>>> 0 == False
True
>>> 1 == False
False
>>> 0 == True
False
Хотя исходный код, вероятно, трудно понять, я надеюсь, что я достаточно хорошо объяснил концепции (исходный код для реализации CPython, реализация в других реализациях Python, таких как PyPy, IronPython может отличаться!). Важным выводом должно быть то, что Python не делает неявных преобразований при проверке равенства, а тестирование равенства не связано вообще с тестированием значений истинности. Внедрены встроенные типы, которые почти всегда дают ощутимые результаты:
- все числовые типы реализуют равенство в некотором роде (поплавки сравниваются с целыми числами, сложным по сравнению с целыми числами и поплавками)
- и все не-ноль и не пусто -
truthy
.
Однако, если вы создадите свои собственные классы, вы можете переопределить тестирование равенства и истинности, как вам нравится (и затем вы можете распространять много путаницы)!
1 В некоторых случаях порядок изменяется:
- Если второй операнд является подклассом первого операнда, первые два шага меняются на противоположные.
- Для некоторых неявных проверок равенства идентификатор объекта проверяется перед вызовом методов
__eq__
. Например, при проверке, находится ли какой-либо элемент в списке, т.е.1 in [1,2,3]
.