Étant donné 2 valeurs int, renvoie True si l'une est négative et l'autre est positive
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!
Quelqu'un Pourrait-il expliquer ce qui se passe? J'essaie de faire un one liner:
lambda a, b: (a < 0 != b < 0)
4 réponses
Tous les opérateurs de comparaison en Python ont la même priorité . de plus, Python fait des comparaisons chaînées. Ainsi,
(a < 0 != b < 0)
Se décompose comme suit:
(a < 0) and (0 != b) and (b < 0)
Si l'un d'entre eux est faux, le résultat total de l'expression sera False
.
Ce que vous voulez faire est d'évaluer chaque état séparément, comme suit:
(a < 0) != (b < 0)
Autres variantes, à partir des commentaires:
(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
Votre code ne fonctionne pas comme prévu, car !=
prend supérieur préséance que a < 0
et b < 0
. Comme itzmeontv le suggère dans sa réponse, vous pouvez simplement décider de la priorité vous-même en entourant les composants logiques avec des parenthèses:
(a < 0) != (b < 0)
Votre code tente d'évaluer a < (0 != b) < 0
[MODIFIER]
Comme tzaman le souligne à juste titre, les opérateurs ont la même priorité, mais votre code tente d'évaluer (a < 0) and (0 != b) and (b < 0)
. Entourant votre les composants logiques avec des parenthèses résoudront ceci:
(a < 0) != (b < 0)
La priorité de l'Opérateur: https://docs.python.org/3/reference/expressions.html#operator-precedence
Comparaisons (par exemple chaînage): https://docs.python.org/3/reference/expressions.html#not-in
Vous pouvez utiliser ceci
return (a < 0) != (b < 0)
Comparaisons peuvent être enchaînés de manière arbitraire, par exemple, x
Donc ça devient
(a < 0) and (0 != b) and (b < 0)
Voir https://docs.python.org/3/reference/expressions.html#not-in
En Python, les opérateurs de comparaison ont la même priorité, et ils sont non associatifs. Il existe une règle distincte pour les séquences d'opérateurs de comparaison, la règle de chaînage. la documentation Python indique à ce sujet:
Si
a, b, c, ..., y, z
sont des expressions etop1, op2, ..., opN
sont les opérateurs de comparaison, puis unop1 b op2 c ... y opN z
est équivalent àa op1 b and b op2 c and ... y opN z
, sauf que chaque expression est évaluée au plus une fois.
En outre, a op1 b and b op2 c and ... y opN z
évalue de gauche à droite.
a < 0 and 0 != b and b < 0
a < 0
va évalué à False
, et l'évaluation ultérieure sera arrêtée en raison de évaluation de court-circuit . Ainsi, l'expression entière sera évaluée comme False
.