992 Stimmen

Wie erhält man das logische Xor zweier Variablen in Python?

Wie erhalten Sie die logisches Xor von zwei Variablen in Python?

Ich habe zum Beispiel zwei Variablen, von denen ich erwarte, dass sie Zeichenketten sind. Ich möchte testen, ob nur eine von ihnen einen wahren Wert enthält (also nicht None oder die leere Zeichenkette ist):

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

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

>>> 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'

6 Stimmen

Wie definiert man "xor" für ein Paar von Zeichenketten? Was sollte "abc" ^ "" Ihrer Meinung nach zurückgeben, was es nicht tut?

25 Stimmen

Es sollte True zurückgeben, anstatt eine Exception auszulösen, da nur eine der Zeichenketten True ist, wie durch den normalen Python-Typ bool definiert.

72 Stimmen

Ich bin erstaunt, dass Python keinen Infix-Operator namens "xor" hat, was die intuitivste, pythonische Implementierung wäre. Die Verwendung von "^" ist konsistent mit anderen Sprachen, aber nicht so offensichtlich lesbar wie das meiste in Python.

1698voto

A. Coady Punkte 49113

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

bool(a) != bool(b)

245 Stimmen

Das ist zwar clever und kurz, aber ich bin nicht überzeugt, dass es sauber ist. Wenn jemand dieses Konstrukt im Code liest, ist ihm dann 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.

73 Stimmen

Vielleicht ist "ist es klar, dass es ein XOR ist?" die falsche Frage. Wir wollten nur herausfinden, ob die Antwort auf zwei Fragen die gleiche ist, und dachten, wir würden XOR verwenden, um das zu realisieren. Wenn wir zum Beispiel sicherstellen wollen, dass wir nicht Äpfel mit Birnen vergleichen, ist dann "if xor( isApple(x), isApple(y) )" wirklich eindeutiger als "if isApple(x) != isApple(y)"? Für mich nicht!

138 Stimmen

Es gibt ein Problem bei 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). Das gilt auch für Casts auf bool, aber ich würde ^ empfehlen. Um zu wissen, was im ersten Beispiel vor sich geht, schlagen Sie "Operatorverkettung" nach.

701voto

Zach Hirsch Punkte 22123

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

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

Aber das ist mir ein bisschen zu langatmig und auf den ersten Blick nicht besonders klar. Eine andere Möglichkeit ist es, dies zu tun:

bool(a) ^ bool(b)

Der xor-Operator für zwei Boolesche Werte ist ein logisches xor (anders als bei Ints, wo er bitweise ist). Das macht Sinn, da bool ist nur eine Unterklasse von int aber so implementiert ist, dass sie nur die Werte 0 y 1 . Und logisches xor ist äquivalent zu bitweisem xor, wenn die Domäne beschränkt ist auf 0 y 1 .

Also die logical_xor Funktion würde wie folgt implementiert werden:

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

Kredit an Nick Coghlan auf der Python-3000 Mailingliste .

16 Stimmen

Toller Beitrag, aber warum ausgerechnet "str1" und "str2"?

2 Stimmen

@Token warum nicht. Meinen Sie, weil sie nicht sehr pythonisch sind?

0 Stimmen

@orokusaki: weil sie ihren Verwendungszweck nicht sehr gut zu vermitteln scheinen.

247voto

singingwolfboy Punkte 5038

Bitweise exclusive-or ist bereits in Python eingebaut, in der operator Modul (das identisch ist mit dem ^ Operator):

from operator import xor
xor(bool(a), bool(b))  # Note: converting to bools is essential

4 Stimmen

Das ist es, was ich brauchte. Beim Reverse-Engineering von Malware werden Strings oft bis zu einer XOR-Operation vermischt. Mit diesem chr(xor(ord("n"), 0x1A)) = 't'

104 Stimmen

Seien Sie vorsichtig, auch dies ist bitweise: xor(1, 2) gibt zurück. 3 . Aus dem Docstring: xor(a, b) -- Same as a ^ b. Denken Sie daran, dass alles, was aus operator ist nur eine funktionale Form eines bestehenden eingebauten Infix-Operators.

12 Stimmen

@askewchan: Die bool Typenüberlastungen __xor__ um Boolesche Werte zurückzugeben. Es wird gut funktionieren, aber es ist Overkill, wenn bool(a) ^ bool(b) macht genau das Gleiche.

57voto

ddaa Punkte 49943

Als Zach erklärt, 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 von einer logischen Diagrammsprache inspiriert, die ich in der Schule gelernt habe und in der "ODER" durch ein Kästchen dargestellt wurde, das 1 (größer oder gleich 1) und "XOR" wurde durch ein Kästchen gekennzeichnet, das =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 ein "exklusives oder", das heißt "eines unter Ausschluss der anderen".

13 Stimmen

Also, True + True + False + True == 3, und 3 != 1, aber True XOR True XOR False XOR True == True. Können Sie die "korrekte Implementierung von XOR bei mehreren Operanden" näher erläutern?

0 Stimmen

@: Wickeln Sie es in ein bool()

5 Stimmen

@tzot Ihr Beispiel scheitert, weil Sie nach der Lösung von ddaa die Addition nur auf zwei Variablen gleichzeitig anwenden. Der richtige Weg, das Ganze auszuschreiben, müsste also lauten (((((True + True)==1)+False)==1)+True)==1 . Die hier gegebene Antwort lässt sich vollständig auf mehrere Operanden verallgemeinern.

36voto

nosklo Punkte 204121
  • Python logisch or : A or B : kehrt zurück A si bool(A) es True , andernfalls wird B
  • Python logisch and : A and B : kehrt zurück A si bool(A) es False , andernfalls wird B

Um den Großteil dieser Denkweise beizubehalten, würde meine logische xor-Definition lauten:

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

Auf diese Weise kann es zurückkehren a , b , oder False :

>>> logical_xor('this', 'that')
False
>>> logical_xor('', '')
False
>>> logical_xor('this', '')
'this'
>>> logical_xor('', 'that')
'that'

6 Stimmen

Das erscheint mir schlecht oder zumindest seltsam. Keiner der anderen eingebauten logischen Operatoren gibt einen der drei möglichen Werte zurück.

2 Stimmen

@Zach Hirsch: Deshalb habe ich gesagt "zu halten Die meisten dieser Denkweise" - da es kein gutes Ergebnis gibt, wenn beides wahr oder falsch ist

0 Stimmen

Eine logische Operation muss einen logischen Wert zurückgeben, daher sieht das zweite "return a or b" seltsam aus, also muss das zweite return True zurückgeben.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X