Wie erhält man das logische xor von zwei Variablen in Python?

647

Wie erhält man das logische xor von zwei Variablen in Python?

Zum Beispiel habe ich zwei Variablen, von denen ich erwarte, dass sie Zeichenfolgen sind. Ich möchte testen, ob nur einer von ihnen einen True-Wert enthält (nicht None oder die leere Zeichenfolge):

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
if logical_xor(str1, str2):
    print "ok"
else:
    print "bad"

Der ^Operator scheint bitweise zu sein und nicht für alle Objekte definiert zu sein:

>>> 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'
Zach Hirsch
quelle
3
Wie definieren Sie "xor" für ein paar Strings? Was denkst du, sollte "abc" ^ "" zurückgeben, was es nicht tut?
Mehrdad Afshari
18
Es sollte True zurückgeben, anstatt eine Ausnahme auszulösen, da nur eine der Zeichenfolgen True ist, wie vom normalen Python-Bool-Typ definiert.
Zach Hirsch
38
Ich bin erstaunt, dass Python keinen Infix-Operator namens "xor" hat, was die intuitivste Pythonic-Implementierung wäre. Die Verwendung von "^" stimmt mit anderen Sprachen überein, ist jedoch nicht so gut lesbar wie die meisten von Python.
Mark E. Haase
13
@MehrdadAfshari Die offensichtliche Antwort auf Ihre Frage ist , dass ist a xor adefiniert als (a and not b) or (not a and b), und so a xor b, wenn aund bZeichenketten sind, oder alle anderen Arten sollten unabhängig ergeben (a and not b) or (not a and b)Ausbeuten.
Kaz
1
Das Problem ist, dass die Dokumentation schlecht ist. ^ ist "bitweise exklusiv oder", was wörtlich interpretiert bedeutet, Stück für Stück, nicht Bool für Bool. x'FFFF00 '^ x'FFFF00' sollte also x'000000 'sein. Oder soll dies nur auf Char-by-Char-Basis geschehen? als Zahlen gegossen? Wir müssen die kürzeren Zeichenfolgen iterieren, um sie an die Länge der längeren Zeichenfolge anzupassen. All dies sollte eingebaut werden.
McKenzm

Antworten:

1187

Wenn Sie die Eingaben bereits auf Boolesche Werte normalisieren, ist! = Xor.

bool(a) != bool(b)
A. Coady
quelle
147
Obwohl dies klug und kurz ist, bin ich nicht davon überzeugt, dass es sauber ist. Wenn jemand dieses Konstrukt im Code liest, ist ihm sofort klar, dass es sich um eine xor-Operation handelt? Ich fühlte mich verpflichtet, einen Kommentar hinzuzufügen - ein Zeichen für mich, dass ich unklaren Code schreibe und versuche, mich mit einem Kommentar zu entschuldigen.
47
Vielleicht "ist es klar, dass es ein XOR ist?" ist die falsche Frage. Wir haben nur versucht herauszufinden, ob die Antwort auf zwei Fragen gleich ist, und dachten, wir würden XOR verwenden, um dies zu implementieren. Wenn wir beispielsweise sicherstellen möchten, dass wir keine Äpfel mit Orangen vergleichen, ist "wenn xor (isApple (x), isApple (y))" wirklich klarer als "wenn isApple (x)! = IsApple (y)"? Nicht für mich!
AmigoNico
105
Es gibt ein Problem mit der Verwendung von "! =" Als xor. Sie würden wahrscheinlich erwarten, dass bool (a)! = Bool (b)! = Bool (c) dasselbe ist wie bool (a) ^ bool (b) ^ bool (c). Also mache Casts zu Bool, aber ich würde ^ empfehlen. Um zu wissen, was im ersten Beispiel vor sich geht, lesen Sie "Operator Chaining".
Elmo
19
@elmo: +1, um auf den Unterschied hinzuweisen, und +1, um mir beizubringen, was Operator-Verkettung ist! Ich bin im Lager, das sagt, dass! = Nicht so lesbar ist wie ^.
Mark E. Haase
13
sollte es bool(a) is not bool(b)stattdessen sein?
RNA
484

Sie können immer die Definition von xor verwenden, um sie aus anderen logischen Operationen zu berechnen:

(a and not b) or (not a and b)

Aber das ist mir etwas zu ausführlich und auf den ersten Blick nicht besonders klar. Ein anderer Weg, dies zu tun, ist:

bool(a) ^ bool(b)

Der xor-Operator für zwei Boolesche Werte ist logisch xor (im Gegensatz zu Ints, wo er bitweise ist). Was Sinn macht, da booles sich nur um eine Unterklasse von handeltint , aber implementiert wird, um nur die Werte 0und zu haben 1. Und logisches xor entspricht bitweisem xor, wenn die Domäne auf 0und beschränkt ist 1.

Die logical_xorFunktion würde also wie folgt implementiert:

def logical_xor(str1, str2):
    return bool(str1) ^ bool(str2)

Dank an Nick Coghlan auf der Python-3000-Mailingliste .

Zach Hirsch
quelle
7
Toller Beitrag, aber ausgerechnet, um Ihre Parameter zu benennen, warum 'str1' und 'str2'?
SingleNegationElimination
1
@Token warum nicht. Meinst du, weil sie nicht sehr pythonisch sind?
Orokusaki
1
@Zach Hirsch Könnten Sie (nicht a und b) anstelle von (b und nicht a) zur besseren Lesbarkeit verwenden oder wäre die Definition nicht mit xor vereinbar?
Orokusaki
10
Sie sollten die Nots zuerst (not b and a) or (not a and b)so setzen, damit die Zeichenfolge zurückgegeben wird, falls vorhanden, was wie die pythonische Funktionsweise der Funktion erscheint.
rjmunro
2
@TokenMacGuy: Was hast du vorgeschlagen, er sollte sie stattdessen benennen?
user541686
179

Bitweise exklusiv - oder ist bereits in Python im operatorModul integriert (identisch mit dem ^Operator):

from operator import xor
xor(bool(a), bool(b))  # Note: converting to bools is essential
singender Wolfsjunge
quelle
3
Das brauchte ich. Beim Reverse Engineering von Malware werden Zeichenfolgen häufig bis zu einer XOR-Operation entstellt. Mit diesem chr (xor (ord ("n"), 0x1A)) = 't'
ril3y
75
Seien Sie vorsichtig, dies ist auch bitweise: xor(1, 2)kehrt zurück 3. Aus der Dokumentzeichenfolge: xor(a, b) -- Same as a ^ b. Denken Sie daran, dass alles, was aus importiert operatorwird, nur eine funktionale Form eines vorhandenen integrierten Infix-Operators ist.
Askewchan
5
@askewchan: Der boolTyp wird überladen __xor__, um Boolesche Werte zurückzugeben. Es wird gut funktionieren, aber es ist übertrieben, wenn bool(a) ^ bool(b)es genau das Gleiche tut.
Martijn Pieters
@MartijnPieters Der ^Operator ruft __xor__intern auf.
Quantum7
5
@ Quantum7: Ja, ich bin mir nicht sicher, warum du mir das erzählst. Ich habe gerade gesagt, dass der boolTyp die __xor__Methode speziell^ implementiert , weil er sie aufruft . Der Punkt ist, dass gut bool(a) ^ bool(b)funktioniert, es besteht keine Notwendigkeit, die zu verwendenoperator.xor() Funktion hier nicht verwendet werden.
Martijn Pieters
43

Wie Zach erklärte, können Sie verwenden:

xor = bool(a) ^ bool(b)

Ich persönlich bevorzuge einen etwas anderen Dialekt:

xor = bool(a) + bool(b) == 1

Dieser Dialekt ist inspiriert von einer logischen Diagrammsprache, die ich in der Schule gelernt habe, in der "ODER" durch ein Kästchen mit ≥1(größer oder gleich 1) und "XOR" durch ein Kästchen mit =1.

Dies hat den Vorteil, dass exklusive oder mehrere Operanden korrekt implementiert werden.

  • "1 = a ^ b ^ c ..." bedeutet, dass die Anzahl der wahren Operanden ungerade ist. Dieser Operator ist "Parität".
  • "1 = a + b + c ..." bedeutet, dass genau ein Operand wahr ist. Dies ist "exklusiv oder" und bedeutet "eins unter Ausschluss der anderen".
ddaa
quelle
12
Also, True + True + False + True == 3 und 3! = 1, aber True XOR True XOR False XOR True == True. Können Sie näher darauf eingehen, "XOR auf mehreren Operanden korrekt zu implementieren"?
Zot
3
@tzot Ihr Beispiel schlägt fehl, da Sie gemäß der Lösung von ddaa die Addition nur auf zwei Variablen gleichzeitig anwenden. Der richtige Weg, alles aufzuschreiben, müsste also sein (((((True + True)==1)+False)==1)+True)==1. Die hier gegebene Antwort verallgemeinert sich vollständig auf mehrere Operanden.
Ely
6
Es gibt auch einen Unterschied zwischen einem Drei-Wege-XOR und einem nach Ordnungsreihenfolge gruppierten Satz von zwei XORs. 3-WAY-XOR (A, B, C) ist also nicht dasselbe wie XOR (XOR (A, B), C). Und das Beispiel von ddaa ist das erstere, während Ihr Beispiel das letztere annimmt.
Ely
3
@ Mr.F Ihre Erklärung entschuldigt diese Antwort nicht wirklich. In Python, wenn Sie nur tun True + True + False + True, Sie tun bekommen 3, und True + True + False + True == 3gibt zurück , Truewährend True + True + False + True == 1zurück gibt False. Mit anderen Worten, die Antwort hier verallgemeinert sich nicht richtig. Dazu müssen Sie zusätzliche Arbeit leisten. Inzwischen True ^ True ^ False ^ Truefunktioniert ein einfaches wie erwartet.
jpmc26
3
@ jpmc26 Ich verstehe deinen Kommentar nicht. Der Additionsansatz soll die Operation verallgemeinern, bei der Sie überprüfen möchten, ob genau ein Operand Trueein Multi-Arity-XOR ist. Dies ist eine andere Operation als zum Beispiel A XOR B XOR ... XOR Z. Mit anderen Worten, wenn Sie die additionsbasierte Version verwenden möchten True + True + False + True, sollten Sie nach dem Senden der Operanden in erwarten, dass das Ergebnis Falsemehr als eines davon ist True, was funktioniert, wenn die Bedingung dies überprüft == 1.
Ely
26
  • Python logisch or: A or B: Erträge , Awenn bool(A)ist True, sonst kehrtB
  • Python logisch and: A and B: Erträge , Awenn bool(A)ist False, sonst kehrtB

Um den größten Teil dieser Denkweise beizubehalten, wäre meine logische xor Definition:

def logical_xor(a, b):
    if bool(a) == bool(b):
        return False
    else:
        return a or b

Auf diese Weise können sie zurückkehren a, boder False:

>>> logical_xor('this', 'that')
False
>>> logical_xor('', '')
False
>>> logical_xor('this', '')
'this'
>>> logical_xor('', 'that')
'that'
nosklo
quelle
5
Das scheint mir schlecht oder zumindest komisch. Keiner der anderen integrierten logischen Operatoren gibt einen von drei möglichen Werten zurück.
Zach Hirsch
2
@ Zach Hirsch: Deshalb habe ich gesagt, "um den größten Teil dieser Denkweise
beizubehalten
Die logische Operation muss einen logischen Wert zurückgeben, sodass die zweite "Rückgabe a oder b" seltsam aussieht, sodass die zweite Rückgabe True zurückgeben muss.
Denis Barmenkov
9
@Denis Barmenkov: Nun, beachten Sie, dass Python logische Operatoren andund ornicht logischen Wert zurück. 'foo' and 'bar'kehrt zurück 'bar'...
nosklo
6
Auf den ersten Blick scheinen die beiden vorherigen Antworten die besten zu sein, aber auf den zweiten Blick ist diese tatsächlich die einzig wirklich richtige, dh sie ist die einzige, die ein Beispiel für eine xorImplementierung liefert, die mit dem integrierten andund übereinstimmt or. Natürlich sind sie in praktischen Situationen bool(a) ^ bool(b)oder sogar a ^ b(wenn aund bwie bekannt bool) prägnanter.
Erik Kaplun
23

Ich habe verschiedene Ansätze getestet und not a != (not b) schien der schnellste zu sein.

Hier sind einige Tests

%timeit not a != (not b)
10000000 loops, best of 3: 78.5 ns per loop

%timeit bool(a) != bool(b)
1000000 loops, best of 3: 343 ns per loop

%timeit not a ^ (not b)
10000000 loops, best of 3: 131 ns per loop

Bearbeiten: In den obigen Beispielen 1 und 3 fehlen Klammern, sodass das Ergebnis falsch ist. Neue Ergebnisse + truth()Funktion wie von ShadowRanger vorgeschlagen.

%timeit  (not a) ^  (not b)   # 47 ns
%timeit  (not a) != (not b)   # 44.7 ns
%timeit truth(a) != truth(b)  # 116 ns
%timeit  bool(a) != bool(b)   # 190 ns
Rugnar
quelle
6
Das sind 100 ns meines Lebens, die ich nicht zurück bekomme ;-)
Arel
4
Für ein Zwischen-Timing können Sie from operator import trutham oberen Rand des Moduls testen truth(a) != truth(b). boolein Konstruktor Wesen hat eine Menge von unvermeidbaren Overhead an der C - Ebene (es muss Argumente als äquivalent akzeptiert *args, **kwargsdie und analysiert tupleund dictsie zu extrahieren), wobei truth(eine Funktion ist) kann einen optimierten Pfad verwenden, der nicht erfordert entweder ein tupleoder a dictund läuft in etwa der Hälfte der Zeit von boolbasierten Lösungen (aber immer noch länger als notbasierte Lösungen).
ShadowRanger
9

Belohnungsthread:

Anoder Idee ... Versuchen Sie einfach den (möglicherweise) pythonischen Ausdruck «ist nicht», um das Verhalten des logischen «xor» zu erhalten.

Die Wahrheitstabelle wäre:

>>> True is not True
False
>>> True is not False
True
>>> False is not True
True
>>> False is not False
False
>>>

Und für Ihre Beispielzeichenfolge:

>>> "abc" is not  ""
True
>>> 'abc' is not 'abc' 
False
>>> 'abc' is not '' 
True
>>> '' is not 'abc' 
True
>>> '' is not '' 
False
>>> 

Jedoch; Wie oben angegeben, hängt es vom tatsächlichen Verhalten ab, das Sie bei einigen Saiten herausziehen möchten, da Saiten keine Boleans sind ... und noch mehr: Wenn Sie in Python eintauchen, finden Sie "The Peculiar Nature of". und "und" oder "» http://www.diveintopython.net/power_of_introspection/and_or.html

Entschuldigung, mein geschriebenes Englisch, es ist nicht meine geborene Sprache.

Grüße.

Agustin Marcos
quelle
Ich lese es auch als "streng anders". Dies liegt daran, dass einige Sprachen die Operation Stück für Stück der Binärdarstellung implementieren und den Bool der resultierenden bitweisen Operation übernehmen. Ich denke, Ihre Antwort ist eher "typgeschützt", weil sie über den booleschen Raum hinausgeht.
Yucer
Ich meine die Tatsache, dass Ihre Antwort den Fall des Vergleichs von None, False '' abdeckt, da das Unterscheidungsmerkmal anders ist. Zum Beispiel: bool (False)! = Bool ('') trotzdem ist False nicht '' "stimmt mehr mit dieser Semantik von" streng anders "
überein
8

Python hat einen bitweisen Exklusiv-ODER-Operator ^:

>>> True ^ False
True
>>> True ^ True
False
>>> False ^ True
True
>>> False ^ False
False

Sie können es verwenden, indem Sie die Eingaben in Boolesche Werte konvertieren, bevor Sie xor ( ^) anwenden :

bool(a) ^ bool(b)

(Bearbeitet - danke Arel)

Tomer Gal
quelle
Ihre Antwort sollte klarstellen, dass ^es sich um ein bitweises xor handelt (nicht um ein logisches xor wie die gestellte Frage). bool(2) ^ bool(3)gibt eine andere Antwort als bool(2 ^ 3).
Arel
1
@Arel Aber das ist nicht der Fall. a ^ bist polymorph. Wenn aund bsind boolInstanzen, wird das Ergebnis boolals gut. Dieses Verhalten kann kaum als "bitweises" xor bezeichnet werden.
Alfe
@Alfe der wichtige Punkt ist, dass Werte zuerst in Boolesche Werte umgewandelt werden müssen. Die Python-Dokumentation wird ^als bitweise definiert , obwohl es ein interessanter Punkt ist, für den Typen boolund intTypen beibehalten werden. Hinweis: True ^ 2zeigt 3, wie es tatsächlich bitweise ist.
Arel
@Arel Ja, der bool ^ intFall ist, alles intzuerst zu besetzen . Dennoch hat Python eingebauten dem ^Operator für viele Bits in intund für die ein Bit in a dargestellt bool, so sind beide bitweise , aber die bitweise xor für ein einzelnes Bit nur ist die logische xor für booleans.
Alfe
Ich hasse es immer, diesen Operator zu verwenden, obwohl ich verstehe xor, dass er sich aus technischer Sicht instinktiv wie eine mathematische Kraft anfühlt, dh 2^3 = pow(2,3)ich kommentiere immer explizit, um Verwirrung zu vermeiden.
Nicholas Hamilton
8

Da ich die einfache Variante von xor nicht sehe, die variable Argumente verwendet und nur die Wahrheitswerte True oder False verwendet, werde ich sie hier nur für jedermann verwenden. Es ist, wie von anderen bemerkt, hübsch (um nicht sehr zu sagen) unkompliziert.

def xor(*vars):
    sum = False
    for v in vars:
        sum = sum ^ bool(v)
    return sum

Auch die Verwendung ist unkompliziert:

if xor(False, False, True, False):
    print "Hello World!"

Da dies das verallgemeinerte n-ary logische XOR ist, ist sein Wahrheitswert immer dann True, wenn die Anzahl der True-Operanden ungerade ist (und nicht nur, wenn genau einer True ist, dies ist nur ein Fall, in dem n-ary XOR True ist).

Wenn Sie also nach einem n-ary-Prädikat suchen, das nur dann True ist, wenn genau einer seiner Operanden ist, möchten Sie möglicherweise Folgendes verwenden:

def isOne(*vars):
    sum = False
    for v in vars:
        if sum and v:
            return False
        else:
            sum = sum or v
    return sum
Micdah
quelle
Zur Verbesserung dieser Antwort : (bool(False) is False) == True. Sie können nur Falseauf diesen Zeilen verwenden.
Pathunstrom
7

Exklusiv Oder ist wie folgt definiert

def xor( a, b ):
    return (a or b) and not (a and b)
S.Lott
quelle
2
das würde True für xor ('this', '') zurückgeben und um Pythons Weg zu folgen, sollte es 'this' zurückgeben.
Nosklo
@nosklo: Nehmen Sie es mit der BDFL auf, bitte nicht ich. Da Python True zurückgibt, muss dies Pythons Weg sein.
S.Lott
2
Ich meine aus Gründen der Konsistenz mit den anderen logischen Python-Operatoren - Python gibt nicht True zurück, wenn ich dies tue ('this' oder ''), sondern 'this'. Aber in Ihrer Funktion gibt xor ('this', '') True zurück. Es sollte 'this' zurückgeben, wie es das eingebaute "oder" Python tut.
Nosklo
10
Python andund orKurzschluss machen. Jede xorImplementierung kann nicht kurzschließen, daher besteht bereits eine Diskrepanz. Daher gibt es keinen Grund, der xorwie and+ ordo funktionieren sollte .
Zot
7

Manchmal arbeite ich mit 1 und 0 anstelle von booleschen True- und False-Werten. In diesem Fall kann xor definiert werden als

z = (x + y) % 2

welches die folgende Wahrheitstabelle hat:

     x
   |0|1|
  -+-+-+
  0|0|1|
y -+-+-+
  1|1|0|
  -+-+-+
Steve L.
quelle
7

Ich weiß, dass dies spät ist, aber ich hatte einen Gedanken und es könnte sich lohnen, nur zur Dokumentation. Vielleicht würde das funktionieren: np.abs(x-y)Die Idee ist das

  1. Wenn x = True = 1 und y = False = 0, wäre das Ergebnis | 1-0 | = 1 = True
  2. Wenn x = False = 0 und y = False = 0, wäre das Ergebnis | 0-0 | = 0 = False
  3. Wenn x = True = 1 und y = True = 1, wäre das Ergebnis | 1-1 | = 0 = False
  4. Wenn x = False = 0 und y = True = 1, wäre das Ergebnis | 0-1 | = 1 = True
BarocliniCplusplus
quelle
7

Einfach, leicht zu verstehen:

sum( (bool(a), bool(b) ) == 1

Wenn Sie nach einer exklusiven Auswahl suchen, kann diese auf mehrere Argumente erweitert werden:

sum( bool(x) for x in y ) % 2 == 1
cz
quelle
1
sum(map(bool, y)) % 2 == 1
Warvariuc
6

Wie wäre es damit?

(not b and a) or (not a and b)

wird geben, awenn bfalsch ist,
wird geben, bwenn afalsch ist,
wird gebenFalse anders

Oder mit dem ternären Ausdruck Python 2.5+:

(False if a else b) if b else a
Markus Jarderot
quelle
6

Einige der hier vorgeschlagenen Implementierungen führen in einigen Fällen zu einer wiederholten Bewertung der Operanden, was zu unbeabsichtigten Nebenwirkungen führen kann und daher vermieden werden muss.

Das heißt, eine xorImplementierung, die entweder zurückgibt Trueoder Falseziemlich einfach ist; Eine, die nach Möglichkeit einen der Operanden zurückgibt, ist viel schwieriger, da kein Konsens darüber besteht, welcher Operand der ausgewählte sein soll, insbesondere wenn mehr als zwei Operanden vorhanden sind. Zum Beispiel sollte xor(None, -1, [], True)zurückkehren None, []oderFalse ? Ich wette, jede Antwort erscheint einigen Leuten als die intuitivste.

Für das True- oder das False-Ergebnis gibt es bis zu fünf mögliche Optionen: Rückgabe des ersten Operanden (wenn er mit dem Endergebnis im Wert übereinstimmt, sonst Boolescher Wert), Rückgabe der ersten Übereinstimmung (wenn mindestens einer vorhanden ist, sonst Boolescher Wert), letzten Operanden zurückgeben (wenn ... sonst ...), letzte Übereinstimmung zurückgeben (wenn ... sonst ...) oder immer boolesch zurückgeben. Insgesamt sind das 5 ** 2 = 25 Geschmacksrichtungen xor.

def xor(*operands, falsechoice = -2, truechoice = -2):
  """A single-evaluation, multi-operand, full-choice xor implementation
  falsechoice, truechoice: 0 = always bool, +/-1 = first/last operand, +/-2 = first/last match"""
  if not operands:
    raise TypeError('at least one operand expected')
  choices = [falsechoice, truechoice]
  matches = {}
  result = False
  first = True
  value = choice = None
  # avoid using index or slice since operands may be an infinite iterator
  for operand in operands:
    # evaluate each operand once only so as to avoid unintended side effects
    value = bool(operand)
    # the actual xor operation
    result ^= value
    # choice for the current operand, which may or may not match end result
    choice = choices[value]
    # if choice is last match;
    # or last operand and the current operand, in case it is last, matches result;
    # or first operand and the current operand is indeed first;
    # or first match and there hasn't been a match so far
    if choice < -1 or (choice == -1 and value == result) or (choice == 1 and first) or (choice > 1 and value not in matches):
      # store the current operand
      matches[value] = operand
    # next operand will no longer be first
    first = False
  # if choice for result is last operand, but they mismatch
  if (choices[result] == -1) and (result != value):
    return result
  else:
    # return the stored matching operand, if existing, else result as bool
    return matches.get(result, result)

testcases = [
  (-1, None, True, {None: None}, [], 'a'),
  (None, -1, {None: None}, 'a', []),
  (None, -1, True, {None: None}, 'a', []),
  (-1, None, {None: None}, [], 'a')]
choices = {-2: 'last match', -1: 'last operand', 0: 'always bool', 1: 'first operand', 2: 'first match'}
for c in testcases:
  print(c)
  for f in sorted(choices.keys()):
    for t in sorted(choices.keys()):
      x = xor(*c, falsechoice = f, truechoice = t)
      print('f: %d (%s)\tt: %d (%s)\tx: %s' % (f, choices[f], t, choices[t], x))
  print()

quelle
5

Viele Leute, einschließlich mir, benötigen eine xorFunktion, die sich wie eine xor-Schaltung mit n Eingängen verhält, wobei n variabel ist. (Siehe https://en.wikipedia.org/wiki/XOR_gate ). Die folgende einfache Funktion implementiert dies.

def xor(*args):
   """
   This function accepts an arbitrary number of input arguments, returning True
   if and only if bool() evaluates to True for an odd number of the input arguments.
   """

   return bool(sum(map(bool,args)) % 2)

Beispiel-E / A folgt:

In [1]: xor(False, True)
Out[1]: True

In [2]: xor(True, True)
Out[2]: False

In [3]: xor(True, True, True)
Out[3]: True
Phillip M. Feldman
quelle
5

So erhalten Sie das logische xor von zwei oder mehr Variablen in Python:

  1. Konvertieren Sie Eingaben in Boolesche Werte
  2. Verwenden Sie den bitweisen xor-Operator ( ^oder operator.xor)

Zum Beispiel,

bool(a) ^ bool(b)

Wenn Sie die Eingaben in Boolesche Werte konvertieren, wird bitweises xor zu logischem xor.

Beachten Sie, dass die akzeptierte Antwort falsch ist: Sie != ist aufgrund der Subtilität der Operatorverkettung nicht mit xor in Python identisch .

Zum Beispiel ist das xor der drei folgenden Werte falsch, wenn !=:

True ^  False ^  False  # True, as expected of XOR
True != False != False  # False! Equivalent to `(True != False) and (False != False)`

(PS Ich habe versucht, die akzeptierte Antwort so zu bearbeiten, dass sie diese Warnung enthält, aber meine Änderung wurde abgelehnt.)

Arel
quelle
4

Es ist einfach, wenn Sie wissen, was XOR tut:

def logical_xor(a, b):
    return (a and not b) or (not a and b)

test_data = [
  [False, False],
  [False, True],
  [True, False],
  [True, True],
]

for a, b in test_data:
    print '%r xor %s = %r' % (a, b, logical_xor(a, b))
Denis Barmenkov
quelle
4

Dies erhält das logische exklusive XOR für zwei (oder mehr) Variablen

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")

any([str1, str2]) and not all([str1, str2])

Das erste Problem bei diesem Setup besteht darin, dass es höchstwahrscheinlich die gesamte Liste zweimal durchläuft und mindestens eines der Elemente mindestens zweimal überprüft. Dies kann das Codeverständnis verbessern, führt jedoch nicht zu einer Geschwindigkeitssteigerung (die sich je nach Anwendungsfall vernachlässigbar unterscheiden kann).

Das zweite Problem bei diesem Setup besteht darin, dass unabhängig von der Anzahl der Variablen die Exklusivität überprüft wird. Dies kann zunächst als Merkmal angesehen werden, aber das erste Problem wird mit zunehmender Anzahl von Variablen (falls dies jemals der Fall ist) viel bedeutender.

Marc
quelle
4

Xor ist ^in Python. Es gibt zurück:

  • Ein bitweises xor für Ints
  • Logisches xor für Bools
  • Eine exklusive Vereinigung für Sets
  • Benutzerdefinierte Ergebnisse für implementierte Klassen __xor__.
  • TypeError für undefinierte Typen wie Zeichenfolgen oder Wörterbücher.

Wenn Sie sie ohnehin für Zeichenfolgen verwenden möchten, boolwird Ihre Operation durch Eingießen eindeutig (Sie könnten auch meinen set(str1) ^ set(str2)).

Arthur Havlicek
quelle
3

XOR ist implementiert in operator.xor.

lbolla
quelle
8
operator.xor entspricht der bitweisen Operation, die das Originalposter nicht möchte.
Niriel
@ Kojiro offensichtlich so!
Arel
3

So würde ich jede Wahrheitstabelle codieren. Insbesondere für xor haben wir:

| a | b  | xor   |             |
|---|----|-------|-------------|
| T | T  | F     |             |
| T | F  | T     | a and not b |
| F | T  | T     | not a and b |
| F | F  | F     |             |

Schauen Sie sich einfach die T-Werte in der Antwortspalte an und setzen Sie alle wahren Fälle mit logischem oder zusammen. Diese Wahrheitstabelle kann also in Fall 2 oder 3 erstellt werden.

xor = lambda a, b: (a and not b) or (not a and b)
Snagpaul
quelle
-6

Wir können xor von zwei Variablen leicht finden, indem wir verwenden:

def xor(a,b):
    return a !=b

Beispiel:

xor (Richtig, Falsch) >>> Richtig

Muhammad Abdullah
quelle
1
oder xor("hey", "there")>>> Stimmt, aber das wollen wir nicht
Mayou36