2015-04-22 2 views
25
def logical_xor(a, b): # for example, -1 and 1 
    print (a < 0) # evaluates to True 
    print (b < 0) # evaluates to False 
    print (a < 0 != b < 0) # EVALUATES TO FALSE! why??? it's True != False 
    return (a < 0 != b < 0) # returns False when it should return True 

print (logical_xor(-1, 1)) # returns FALSE! 

# now for clarification 

print (True != False) # PRINTS TRUE! 

Может ли кто-нибудь объяснить, что происходит? Я пытаюсь сделать один лайнер:Учитывая 2 значения int, return True, если один отрицательный, а другой положительный

lambda a, b: (a < 0 != b < 0) 
+12

Здесь есть урок: используйте круглые скобки. Или, альтернативно, используйте 'print (a * b <0)'. –

+0

'return math.copysign (1, a)! = Math.copysign (1, b)' –

+0

'print (True! = False) # PRINTS TRUE!' Почему вы так удивлены этим? Это _is_ true, что true не равно false. – MikeTheLiar

ответ

31

Все операторы сравнения в Python имеют те same precedence. Кроме того, Python делает прикован сравнения. Таким образом,

(a < 0 != b < 0) 

рассыпается, как:

(a < 0) and (0 != b) and (b < 0) 

Если какой-либо один из них является ложным, общий результат выражения будет False.

То, что вы хотите сделать, это оценить каждое условие в отдельности, например, так:

(a < 0) != (b < 0) 

Другие варианты, от комментариев:

(a < 0) is not (b < 0) # True and False are singletons so identity-comparison works 

(a < 0)^(b < 0) # bitwise-xor does too, as long as both sides are boolean 

(a^b < 0) # or you could directly bitwise-xor the integers; 
      # the sign bit will only be set if your condition holds 
      # this one fails when you mix ints and floats though 

(a * b < 0) # perhaps most straightforward, just multiply them and check the sign 
+0

Обратите внимание, что '(a <0)^(b <0)' также работает, и он использует оператор xor. :) Альтернативно, '(a <0) не является (b <0)', так как «True» и «False» являются одиночными, хотя некоторые могут возражать против этого синтаксиса: см. Здесь для обсуждения: http: // stackoverflow. com/q/9494404/4014959 –

+0

'^' for * xor * работает, если booleans сравниваются, но он не будет работать для всех значений, таких как 'и' и 'или' будет ... –

+0

OP специально помечен Python 3.x поэтому я связан с руководствами Python 3. –

5

Вы можете использовать этот

return (a < 0) != (b < 0) 

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

Таким образом, становится

(a < 0) and (0 != b) and (b < 0) 

См https://docs.python.org/3/reference/expressions.html#not-in

+0

почему первый не работает? –

+0

Может быть, это часть приоритета '! =' И '<' – itzMEonTV

+0

'<>' не считается «устаревшей», она вообще была удалена из Python 3.0. –

8

Ваш код не работает надлежащим образом, потому что != занимает больше, чем precedencea < 0 и b < 0. Как itzmeontv предлагает в своем ответе, вы можете просто решить, предшествование себя окружив логические компоненты с круглыми скобками:

(a < 0) != (b < 0) 

Ваш код пытается оценить a < (0 != b) < 0

[EDIT]

Как tzaman справедливо указывает, что операторы имеют одинаковый приоритет, но ваш код пытается оценить (a < 0) and (0 != b) and (b < 0). Ближайшие логические компоненты с помощью скобок будет решить эту проблему:

(a < 0) != (b < 0) 

Оператор старшинства: https://docs.python.org/3/reference/expressions.html#operator-precedence

Сравнения (Iа цепные): https://docs.python.org/3/reference/expressions.html#not-in

+2

Они на самом деле являются ** одинаковым ** приоритетом; отказ заключается в том, что он рассматривается как скованное сравнение. См. [Docs] (https://docs.python.org/2/reference/expressions.html#not-in). – tzaman

+0

@ Xis88: Да, это эквивалентно '(a <0) и (0! = B) и (b <0)'. –

+0

Op специально отмеченный Python 3, поэтому, пожалуйста, обратитесь к руководствам Python 3. –

0

В Python, операторы сравнения имеют одинаковый приоритет, и они неассоциативны. Существует отдельное правило для последовательностей операторов сравнения, правила цепочки.Python documentation государство о том, что:

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

Кроме того, a op1 b and b op2 c and ... y opN z оценивает слева направо.

a < 0 and 0 != b and b < 0 

a < 0 будут оценены, чтобы False, и дальнейшая оценка будет прекращена из-за short-circuit evaluation. Таким образом, все выражение будет оцениваться как False.

+1

Это неправильно! В документации, которую вы цитируете прямо там, говорится, что сравнения скованы. * НЕ * то же самое, что и лево-ассоциативное. – tzaman

+0

@tzaman; Ты прав. – haccks

Смежные вопросы