Неравенства и скобки в Python

Таким образом, в python, условия истинности могут быть легко проверены и с круглыми скобками это расставляет приоритеты в порядке истинных условий, например, это легко понять:

>>> 3 > 2
True
>>> (3 > 2) is True
True

Но что это значит, я не мог понять логику того, почему они возвращают False/True:

>>> 3 > 2 is True
False
>>> 3 > (2 is True)
True
>>> 5 < 3 is False > 2 is True
False
>>> 5 < 3 is False is True > 2 is True
False
>>> 3 < 5 is True is True > 2 is True
False
>>> 3 < 5 is True is True > 2 is True is not False is True
False
>>> 3 < 5 is True is (True > 2 is True is not False) is True
False
>>> 3 < 5 is True is (True > (2 is True) is not False) is True
False
>>> (3 < 5 is True is True) > 2 is (True is not False is True)
False

Я знаю, что это не питонические состояния, но как мне их понимать? Это все еще слева направо?

Или делает is True и / или is False принимает президентство?

3 ответа

Решение

Вы можете проанализировать каждый из этих случаев с dis Модуль, чтобы выяснить, что именно происходит. Например:

In [1]: import dis
In [2]: def test():
   ...:     return 3 > 2 is True
   ...: 
In [3]: dis.dis(test)
  2           0 LOAD_CONST               1 (3)
              3 LOAD_CONST               2 (2)
              6 DUP_TOP             
              7 ROT_THREE           
              8 COMPARE_OP               4 (>)
             11 JUMP_IF_FALSE_OR_POP    21
             14 LOAD_GLOBAL              0 (True)
             17 COMPARE_OP               8 (is)
             20 RETURN_VALUE        
        >>   21 ROT_TWO             
             22 POP_TOP             
             23 RETURN_VALUE

Это означает, что стек выглядит так после каждого шага:

 0: 3
 3: 3 2
 6: 3 2 2
 7: 2 3 2
 8: 2 True
11: 2
14: 2 True
17: False (comparison was: "2 is True")
20: (False is returned)

Для меня это выглядит как ошибка в Python, если честно. Может быть, есть какое-то хорошее объяснение того, почему это происходит, но я бы сообщил об этом выше по течению.

Просто чтобы переписать его эквивалентным образом, код делает:

if 3 > 2:
    if 2 is True:
        return True
return False

Редактировать: Может быть, это на самом деле имеет какой-то странный смысл. Рассмотрим, как работает проверка связанных неравенств:

3 > 2 > 1  ==  3 > 2 and 2 > 1

Если это обобщает до:

x op1 y op2 z == x op1 y and y op2 z

это объяснило бы результат.

Edit2: это на самом деле соответствует документации. Посмотрите на связанные цепочки: https://docs.python.org/2/reference/expressions.html

comparison    ::=  or_expr ( comp_operator or_expr )*
comp_operator ::=  "<" | ">" | "==" | ">=" | "<=" | "<>" | "!="
                   | "is" ["not"] | ["not"] "in"

is считается столь же хорошим сравнением, как >, поэтому применяется стандартное расширение для множественных сравнений.

Другие сравнения должны быть ясны сейчас. Единственная странная новая деталь: True == 1, False == 0, так 3 > False в 3 > (2 is True), Большинство других можно объяснить с помощью расширений. Например:

5  <     3     is       False       >     2     is True  == False
(5 < 3) and (3 is False) and (False > 2) and (2 is True) == False

Boolean Тип в Python является подтипом int, Так True на самом деле 1 и False это 0.

Все операции сравнения в Python имеют одинаковый приоритет (>, <, >=, <=, ==, !=, is [not], [not] in).

Сравнения могут быть связаны произвольно, например, x < y <= z эквивалентно x < y and y <= zза исключением того, что y вычисляется только один раз (но в обоих случаях z вообще не оценивается, когда x < y оказывается ложным).

Формально, если a, b, c,..., y, z выражения и op1, op2,..., opN операторы сравнения, то a op1 b op2 c ... y opN z эквивалентно a op1 b and b op2 c and ... y opN zза исключением того, что каждое выражение оценивается не более одного раза.

См. Справочник по языку Python.

Прежде всего, вам, вероятно, понадобится небольшая шпаргалка, чтобы узнать порядок оценки. Большинство из этих операторов находятся в одной скобке и поэтому оцениваются слева направо. С этим знанием примеры могут быть переведены в их "реальное" значение:

(3 < 5 is True is True) > 2 is (True is not False is True)

эквивалентно: (на самом деле нет __is__ а также __not__потому что это ключевые слова, которые не могут быть перегружены. Это для наглядности)

(3.__lt__(5).__is__(True).__is__(True)).__gt__(2).__is__(True.__is__(False).__not__().__is__(True))

Я мог бы сэкономить некоторые детали, которые описаны здесь. Хорошо, что вы (надеюсь) никогда не пишете такие сложные выражения, что вам нужно проверить документацию, чтобы узнать, что она делает.

РЕДАКТИРОВАТЬ: Неважно, это не работает таким образом с сравнениями. Сравнения сравниваются "все вместе попарно", как описано в ответе Вираптора.

Другие вопросы по тегам