如果给定两个整数值,返回True,如果其中一个是负数而另一个是正数。

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!

有人能解释一下正在发生什么吗?我正在尝试制作一行代码:

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

12
这里有一个教训:使用括号。或者,另一种选择是使用 print(a*b < 0) - David Hammen
return math.copysign(1, a) != math.copysign(1, b) - Jacob Krall
打印(True!= False)#打印真!你为什么对此感到惊讶?确实,真不等于假。 - Mike G
@mikeTheLiar:OP并不感到惊讶;这是他/她最初预期的行为。 - ruakh
2
请勿通过破坏您的帖子给他人带来更多工作。在 Stack Exchange(SE)网络上发布内容,即表示您已授予SE根据CC BY-SA许可证分发该内容的不可撤销权利(即使您未来做出其他选择)。根据SE政策,非破坏性版本将被分发。因此,任何破坏行为都将被撤销。请参见:删除如何工作?…。如果允许删除,则在帖子下方左侧有一个“删除”按钮,但仅适用于浏览器,而不适用于移动应用程序。 - Makyen
4个回答

30

Python中的所有比较运算符优先级相同。此外,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

请注意,(a < 0) ^ (b < 0) 也可以工作,并且它使用的是异或运算符。 :) 或者,(a < 0) is not (b < 0),因为 TrueFalse 是单例,尽管有些人可能会反对这种语法:在这里查看讨论:https://dev59.com/T2kx5IYBdhLWcg3wA_xS - PM 2Ring
如果比较的是布尔值,那么“^”可以用作异或运算符,但它不能像“and”和“or”一样适用于所有值。 - Antti Haapala -- Слава Україні
@OverlordAlex:为什么在Python中它不能导致整数溢出? - supercat
@supercat Python的整数具有无限精度。 - tzaman
1
@supercat:不幸的是,Python没有sign()方法。有人曾经为math包提出过这个方法,但是由于边缘情况上没有达成一致意见,所以它没有被整合进去(根据快速谷歌搜索)。一个解决方法是使用cmp(number, 0),它将返回+1/0/-1。这对于这个问题确实可以起作用。 - Paradise
显示剩余4条评论

7

你的代码不能按照预期工作,因为!=a < 0b < 0有更高的优先级。如itzmeontv在他的答案中建议的那样,你可以通过在逻辑组件周围加上括号来自己决定优先级:

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

你的代码试图评估 a < (0 != b) < 0

[编辑]

正如tzaman所指出的,运算符具有相同的优先级,但你的代码试图评估 (a < 0) and (0 != b) and (b < 0)。用括号括起逻辑组件将解决这个问题:

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

运算符优先级:https://docs.python.org/3/reference/expressions.html#operator-precedence 比较(包括链接):https://docs.python.org/3/reference/expressions.html#not-in

2
它们实际上具有相同的优先级;失败是因为它被视为链式比较。请参阅文档 - tzaman
@Xis88:是的,它等同于(a < 0) and (0 != b) and (b < 0) - PM 2Ring
Op明确标记了Python 3,因此请链接到Python 3手册。 - Antti Haapala -- Слава Україні

4
您可以使用这个。
return (a < 0) != (b < 0)

比较可以任意链接,例如 x < y <= z 相当于 x < y and y <= z,不同之处在于 y 只计算一次(但在两种情况下,当 x < y 为 false 时,z 都不会被计算)。

因此,它变成了:

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

请参见https://docs.python.org/3/reference/expressions.html#not-in

可能是!=<的优先级的一部分。 - itzMEonTV
<> 不再被视为过时的语法,它在 Python 3.0 中已经被完全移除。 - Antti Haapala -- Слава Україні
(请注意,OP标记了问题为[python-3.x]) - Antti Haapala -- Слава Україні

0

在Python中,比较运算符具有相同的优先级,并且它们是非关联的。对于比较运算符序列,有一个单独的规则,即链接规则。Python文档关于此提到:

如果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,但每个表达式最多只计算一次。

此外,a op1 b and b op2 c and ... y opN z从左到右进行计算。

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

a < 0 将被评估为 False,并且由于短路评估,进一步的评估将停止。因此,整个表达式将被评估为False


1
这是错误的!你引用的文档明确说明比较是链式的。这与左结合不是同一件事。 - tzaman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接