Почему "[] == False" оценивается в False, когда "if not []" преуспевает?
Я спрашиваю об этом, потому что я знаю, что питонический способ проверить, пуст ли пуст или нет, это следующее:
my_list = []
if not my_list:
print "computer says no"
else:
# my_list isn't empty
print "computer says yes"
напечатает computer says no
и т.д. Таким образом, это приводит меня к тому, чтобы идентифицировать []
с False
значениями истинности; однако, если я попытаюсь сравнить [] и False "напрямую", я получаю следующее:
>>> my_list == False
False
>>> my_list is False
False
>>> [] == False
False
и т.д.
Что здесь происходит? Я чувствую, что упускаю что-то действительно очевидное.
Ответы
Ответ 1
Оператор if
оценивает все в булевом контексте, это похоже на неявный вызов встроенной функции bool()
.
Вот как вы могли бы проверить, как вещи будут оцениваться оператором if
:
>>> bool([])
False
>>> bool([]) == False
True
См. документацию по Проверка правдоподобия, пустые списки считаются ложными, но это не значит, что они эквивалентны False
.
PEP 285 также имеет отличную информацию о том, почему он был реализован таким образом, см. последнюю брошюру в разделе "Разрешенные проблемы" для части, которая имеет дело с x == True
и x == False
.
Самый убедительный аспект для меня состоит в том, что ==
обычно транзитивен, поэтому a == b
и b == c
подразумевает a == c
. Итак, если бы вы ожидали, и [] == False
были истинными, а '' == False
были истинными, можно было бы предположить, что [] == ''
должен быть истинным (хотя он явно не должен быть на языке без неявного преобразования типа).
Ответ 2
Пустые контейнеры являются "ложными", то есть они оцениваются до False
в булевом контексте. Это не означает, что они буквально равны константе False
.
Другими словами, True
:
bool([]) == False
Значение истины объекта определяется его методом __nonzero__()
или его __len__()
. (В Python 3, __nonzero__()
было переименовано в __bool__()
.) Контейнеры имеют метод __len__()
, поэтому они правдивы, когда в них есть что-то в них и ложные, когда они пусты.
Если пустые контейнеры были буквально равны False
, кстати, любой пустой контейнер был бы равен любому другому пустующему контейнеру: например, {} == ""
был бы True
. И это просто не имеет никакого смысла!
Однако, просто для того, чтобы взорвать ваш разум, следующее True
:
False == 0
Это связано с тем, что булевы являются подклассом целых чисел в Python, а False
- это просто нуль, который печатается немного по-другому.
Ответ 3
Встроенные типы в Python имеют значение истины, которое позволяет вам проверять их на правдивость. См. Тестирование ценности правды.
Это отличается от выражения object == False
, которое выполняет проверку фактического значения (тест равенства). Он использует метод __eq__()
для определения того, являются ли их значения равными.
Ответ 4
В вашем примере оператор not вызывает преобразование вашего списка в логическое. Попробуйте следующее:
>>> not []
True
>>> not [1]
False
"is" и "==" не делают этого преобразования.