Comment obtenir le xor logique de deux variables en Python?
Par exemple, j'ai deux variables qui devraient être des chaînes. Je veux tester qu'un seul d'entre eux contient une valeur True (n'est pas None ou la chaîne vide):
str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
if logical_xor(str1, str2):
print "ok"
else:
print "bad"
L' ^
opérateur semble être au niveau du bit et n'est pas défini sur tous les objets:
>>> 1 ^ 1
0
>>> 2 ^ 1
3
>>> "abc" ^ ""
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for ^: 'str' and 'str'
python
logical-operators
Zach Hirsch
la source
la source
a xor a
est définie comme(a and not b) or (not a and b)
, et donca xor b
, quanda
etb
sont des chaînes de caractères, ou tout autre type, devraient donner n'importe quel(a and not b) or (not a and b)
rendement.Réponses:
Si vous normalisez déjà les entrées en booléens, alors! = Est xor.
la source
bool(a) is not bool(b)
place?Vous pouvez toujours utiliser la définition de xor pour le calculer à partir d'autres opérations logiques:
Mais c'est un peu trop verbeux pour moi, et ce n'est pas particulièrement clair à première vue. Une autre façon de procéder est:
L'opérateur xor sur deux booléens est un xor logique (contrairement aux entiers, où il est au niveau du bit). Ce qui est logique, car
bool
n'est qu'une sous-classe deint
, mais est implémenté pour n'avoir que les valeurs0
et1
. Et xor logique est équivalent à xor au niveau du bit lorsque le domaine est limité à0
et1
.Ainsi, la
logical_xor
fonction serait implémentée comme:Nous remercions Nick Coghlan sur la liste de diffusion Python-3000 .
la source
(not b and a) or (not a and b)
afin qu'il retourne la chaîne s'il y en avait une, ce qui semble être la manière pythonique pour la fonction de fonctionner.Bitwise exclusive-or est déjà intégré à Python, dans le
operator
module (qui est identique à l'^
opérateur):la source
xor(1, 2)
retourne3
. De la docstring:xor(a, b) -- Same as a ^ b.
Rappelez-vous que tout ce qui est importéoperator
n'est qu'une forme fonctionnelle d'un opérateur d'infixe intégré existant.bool
type surcharge__xor__
pour renvoyer des booléens. Cela fonctionnera très bien, mais sa surpuissancebool(a) ^ bool(b)
fait exactement la même chose.^
opérateur appelle en__xor__
interne.bool
type implémente la__xor__
méthode spécifiquement parce^
qu'il l'appelle . Le fait étant que celabool(a) ^ bool(b)
fonctionne bien, il n'est pas nécessaire d'utiliser laoperator.xor()
fonction ici.Comme Zach l'a expliqué, vous pouvez utiliser:
Personnellement, je privilégie un dialecte légèrement différent:
Ce dialecte est inspiré d'un langage de diagramme logique que j'ai appris à l'école où "OU" était désigné par une boîte contenant
≥1
(supérieur ou égal à 1) et "XOR" était désigné par une boîte contenant=1
.Cela présente l'avantage d'implémenter correctement des opérandes exclusifs ou multiples.
la source
(((((True + True)==1)+False)==1)+True)==1
. La réponse donnée ici se généralise totalement à plusieurs opérandes.True + True + False + True
, vous n'obtenez et Redonne en redonne . En d'autres termes, la réponse ici ne se généralise pas correctement; pour cela, vous devez effectuer un travail supplémentaire. En attendant un simple fonctionne comme prévu.3
True + True + False + True == 3
True
True + True + False + True == 1
False
True ^ True ^ False ^ True
True
, un XOR multi-arité. Il s'agit d'une opération différente de celle par exempleA XOR B XOR ... XOR Z
. En d'autres termes, si vous prévoyez d'utiliser la version basée sur des ajouts, les opérandesTrue + True + False + True
doivent alors s'attendre à ce que le résultat soitFalse
supérieur à l'un d'euxTrue
, ce qui fonctionne si la condition vérifie== 1
.or
::A or B
retourneA
sibool(A)
estTrue
, sinon retourneB
and
::A and B
retourneA
sibool(A)
estFalse
, sinon retourneB
Pour garder la plupart de cette façon de penser, ma définition logique xor serait:
De cette façon , il peut revenir
a
,b
ouFalse
:la source
and
etor
ne reviendra pas valeur logique.'foo' and 'bar'
retourne'bar'
...xor
mise en œuvre cohérente avec le haut-and
etor
. Cependant, bien sûr, dans des situations pratiques,bool(a) ^ bool(b)
ou mêmea ^ b
(sia
etb
sont connus pour êtrebool
) sont plus concis bien sûr.J'ai testé plusieurs approches et j'ai
not a != (not b)
semblé être la plus rapide.Voici quelques tests
Modifier: les exemples 1 et 3 ci-dessus manquent de parenthèses, donc le résultat est incorrect. Nouveaux résultats +
truth()
fonction comme suggéré par ShadowRanger.la source
from operator import truth
en haut du module et testertruth(a) != truth(b)
.bool
être un constructeur a beaucoup de surcharge inévitable au niveau C (il doit accepter les arguments comme l'équivalent de*args, **kwargs
et les analysertuple
etdict
les extraire), oùtruth
(étant une fonction) peut utiliser un chemin optimisé qui ne nécessite ni atuple
ni adict
, et s'exécute dans environ la moitié du temps desbool
solutions basées (mais toujours plus longtemps que lesnot
solutions basées).Fil de récompense:
Idée d'anode ... Il suffit d'essayer l'expression (peut-être) pythonique «n'est pas» pour obtenir le comportement du «xor» logique
La table de vérité serait:
Et pour votre exemple de chaîne:
Toutefois; comme ils l'ont indiqué ci-dessus, cela dépend du comportement réel que vous souhaitez retirer sur les chaînes de couple, car les chaînes ne sont pas boléennes ... et plus encore: si vous «Plongez dans Python», vous trouverez «La nature particulière de" et "et" ou "» http://www.diveintopython.net/power_of_introspection/and_or.html
Désolé mon anglais écrit, ce n'est pas ma langue d'origine.
Cordialement.
la source
Python a un opérateur OU exclusif au niveau du bit, c'est
^
:Vous pouvez l'utiliser en convertissant les entrées en booléens avant d'appliquer xor (
^
):(Modifié - merci Arel)
la source
^
s'agit d'un xor au niveau du bit (pas un xor logique comme la question posée).bool(2) ^ bool(3)
donne une réponse différente debool(2 ^ 3)
.a ^ b
est polymorphe. Sia
etb
sont desbool
instances, le résultat serabool
également. Ce comportement peut difficilement être appelé un xor "au niveau du bit".^
comme, même si au niveau du bit , il est un point intéressant que les types sont conservés pourbool
etint
types. Remarque:True ^ 2
est3
, démontrant comment il est en effet au niveau du bit.bool ^ int
cas est en quelque sorte de tout jeter enint
premier. Pourtant, Python a intégré l'^
opérateur pour de nombreux bits dansint
et pour le bit représenté dans abool
, donc les deux sont au niveau du bit , mais le xor au niveau du bit pour un seul bit est juste le xor logique pour les booléens.xor
, venant d'un milieu d'ingénierie, cela me semble instinctivement comme une puissance mathématique,2^3 = pow(2,3)
ce qui signifie que je commente toujours explicitement pour éviter toute confusion.Comme je ne vois pas la simple variante de xor utilisant des arguments variables et uniquement une opération sur les valeurs de vérité True ou False, je vais la jeter ici pour que quiconque puisse l'utiliser. C'est comme noté par d'autres, assez (pour ne pas dire très) simple.
Et l'utilisation est également simple:
Comme il s'agit du XOR logique n-aire généralisé, sa valeur de vérité sera True chaque fois que le nombre d'opérandes True est impair (et pas seulement quand exactement un est True, ce n'est qu'un cas dans lequel le XOR n-aire est True).
Ainsi, si vous êtes à la recherche d'un prédicat n-aire qui n'est vrai que lorsque l'un de ses opérandes est exactement, vous pouvez utiliser:
la source
(bool(False) is False) == True
. Vous pouvez simplement utiliserFalse
sur ces lignes.Exclusif Or est défini comme suit
la source
and
etor
faire un court-circuit. Toutexor
mise en œuvre ne peut pas court-circuiter, il y a donc déjà un écart; par conséquent, il n'y a aucune raison quixor
devrait fonctionner commeand
+or
do.Parfois, je me retrouve à travailler avec 1 et 0 au lieu des valeurs booléennes True et False. Dans ce cas, xor peut être défini comme
qui a la table de vérité suivante:
la source
Je sais que c'est tard, mais j'ai eu une pensée et ça pourrait valoir la peine, juste pour la documentation. Peut-être que cela fonctionnerait:
np.abs(x-y)
L'idée est quela source
Simple, facile à comprendre:
Si un choix exclusif est ce que vous recherchez, il peut être étendu à plusieurs arguments:
la source
sum(map(bool, y)) % 2 == 1
Que dis-tu de ça?
donnera
a
sib
est fauxdonnera
b
sia
est fauxdonnera
False
autrementOu avec l'expression ternaire Python 2.5+:
la source
Certaines des implémentations suggérées ici entraîneront une évaluation répétée des opérandes dans certains cas, ce qui peut entraîner des effets secondaires involontaires et doit donc être évité.
Cela dit, une
xor
implémentation qui renvoie soitTrue
ouFalse
est assez simple; celui qui renvoie l'un des opérandes, si possible, est beaucoup plus délicat, car il n'y a pas de consensus quant à l'opérande qui doit être choisi, surtout lorsqu'il y a plus de deux opérandes. Par exemple, devraitxor(None, -1, [], True)
revenirNone
,[]
ouFalse
? Je parie que chaque réponse apparaît à certaines personnes comme la plus intuitive.Pour le résultat True ou False, il y a jusqu'à cinq choix possibles: retourner le premier opérande (s'il correspond au résultat final en valeur, sinon booléen), retourner la première correspondance (s'il en existe au moins un, sinon booléen), retourne le dernier opérande (si ... sinon ...), retourne la dernière correspondance (si ... sinon ...), ou retourne toujours booléen. Au total, cela fait 5 ** 2 = 25 saveurs de
xor
.la source
Beaucoup de gens, y compris moi-même, ont besoin d'une
xor
fonction qui se comporte comme un circuit xor à n entrées, où n est variable. (Voir https://en.wikipedia.org/wiki/XOR_gate ). La fonction simple suivante implémente cela.Voici un exemple d'E / S:
la source
Pour obtenir le xor logique de deux ou plusieurs variables en Python:
^
ouoperator.xor
)Par exemple,
Lorsque vous convertissez les entrées en booléens, xor au niveau du bit devient xor logique .
Notez que la réponse acceptée est fausse:
!=
n'est pas la même chose que xor en Python en raison de la subtilité du chaînage des opérateurs .Par exemple, le xor des trois valeurs ci-dessous est incorrect lors de l'utilisation
!=
:(PS J'ai essayé de modifier la réponse acceptée pour inclure cet avertissement, mais ma modification a été rejetée.)
la source
C'est facile quand vous savez ce que fait XOR:
la source
Ceci obtient le XOR logique exclusif pour deux (ou plus) variables
Le premier problème avec cette configuration est qu'elle traverse très probablement toute la liste deux fois et, au minimum, vérifiera au moins un des éléments deux fois. Il peut donc augmenter la compréhension du code, mais il ne se prête pas à la vitesse (qui peut différer de manière négligeable selon votre cas d'utilisation).
Le deuxième problème avec cette configuration est qu'elle vérifie l'exclusivité quel que soit le nombre de variables. C'est peut-être au premier abord considéré comme une caractéristique, mais le premier problème devient beaucoup plus important à mesure que le nombre de variables augmente (si jamais elles le font).
la source
Xor est
^
en Python. Il renvoie:__xor__
.Si vous avez l'intention de les utiliser sur des chaînes de toute façon, les intégrer
bool
rend votre opération sans ambiguïté (vous pouvez également signifierset(str1) ^ set(str2)
).la source
XOR est implémenté dans
operator.xor
.la source
C'est ainsi que je coderais n'importe quelle table de vérité. Pour xor en particulier, nous avons:
Regardez simplement les valeurs T dans la colonne de réponse et enchaînez tous les vrais cas avec un ou logique. Donc, cette table de vérité peut être produite dans le cas 2 ou 3. Par conséquent,
la source
Nous pouvons facilement trouver le xor de deux variables en utilisant:
Exemple:
la source
xor("hey", "there")
>>> Vrai, mais ce n'est pas ce que nous voulons