Почему (1 в [1,0] == True) оценивается как False?

153

Когда я смотрел на ответы на этот вопрос , я обнаружил, что не понимаю свой собственный ответ.

Я не очень понимаю, как это анализируется. Почему второй пример возвращает False?

>>> 1 in [1,0]             # This is expected
True
>>> 1 in [1,0] == True     # This is strange
False
>>> (1 in [1,0]) == True   # This is what I wanted it to be
True
>>> 1 in ([1,0] == True)   # But it's not just a precedence issue!
                           # It did not raise an exception on the second example.

Traceback (most recent call last):
  File "<pyshell#4>", line 1, in <module>
    1 in ([1,0] == True)
TypeError: argument of type 'bool' is not iterable

Спасибо за любую помощь. Я думаю, что я должен упустить что-то действительно очевидное.


Я думаю, что это немного отличается от связанного дубликата:

Почему выражение 0 <0 == 0 возвращает False в Python? ,

Оба вопроса связаны с человеческим пониманием выражения. Мне казалось, что есть два способа (на мой взгляд) оценить выражение. Конечно, ни то, ни другое не было правильным, но в моем примере последняя интерпретация невозможна.

Глядя на 0 < 0 == 0вас, можно представить, что каждая половина оценивается и имеет смысл как выражение:

>>> (0 < 0) == 0
True
>>> 0 < (0 == 0)
True

Так что ссылка отвечает, почему это оценивает False:

>>> 0 < 0 == 0
False

Но мой пример 1 in ([1,0] == True)не имеет смысла в качестве выражения, поэтому вместо двух (предположительно неправильных) возможных интерпретаций возможна только одна:

>>> (1 in [1,0]) == True
Питер Вуд
источник
1
Приоритет оператора ... ==связывание более жесткое, чем in, поэтому [1,0] == Trueсначала выполняется оценка, а затем результат, который передается 1 in other_result.
Марк Б
Я удалил тег Python-2.7, так как Python 3.2 ведет себя так же.
lvc
1
@Marc B: не объясняет второе выражение
Скотт Хантер
32
@MarcB, вопрос включал тест с использованием скобок, чтобы опровергнуть эту интерпретацию.
Марк Рэнсом

Ответы:

194

Python фактически применяет здесь оператор сравнения. Выражение переводится на

(1 in [1, 0]) and ([1, 0] == True)

что очевидно False.

Это также происходит для таких выражений, как

a < b < c

которые переводят на

(a < b) and (b < c)

(без оценки b дважды).

См. Документацию по языку Python для получения более подробной информации.

Свен Марнах
источник
40
Дополнительным доказательством этого является 1 in [1, 0] == [1, 0]оценка True.
Эндрю Кларк
9
Я долго думал об этом как о бородавке. Я бы предпочел, чтобы inоператор имел более высокий приоритет, чем другие операторы сравнения, и чтобы он не был цепным. Но, возможно, мне не хватает варианта использования.
Стивен Румбальский
3
хороший улов, я даже не думал об этом. Не имеет смысла разрешать связывание in- в конце концов, x < y < zимеет смысл, но не так много сx in y in z
BlueRaja - Дэнни Пфлугхофт
7
@ Свен Полезно: возможно. Читаемый: определенно нет. Python претендует на то, чтобы эмулировать обычную математическую типографику с этим соглашением, но при использовании с inэтим просто уже не так и делает его совершенно нелогичным.
Конрад Рудольф
6
@KonradRudolph: Я видел, как в математических текстах не раз думали как «1 ≤ x ∈ ℝ», но я в основном согласен с вами.
Свен Марнах