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.

34voto

Rugnar Punkte 2509

Ich habe mehrere 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, so dass 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

17 Stimmen

Das sind 100 ns meines Lebens, die ich nicht zurückbekomme ;-)

6 Stimmen

Für eine Zwischenzeit können Sie Folgendes tun from operator import truth am oberen Rand des Moduls, und testen Sie truth(a) != truth(b) . bool als Konstruktor hat eine Menge unvermeidbaren Overhead auf der C-Ebene (es muss Argumente als Äquivalent von *args, **kwargs und analysiere die tuple et dict um sie zu extrahieren), wobei truth (die eine Funktion ist) kann einen optimierten Pfad verwenden, der weder eine tuple oder eine dict und läuft in etwa der Hälfte der Zeit von bool basierten Lösungen (aber immer noch länger als not basierte Lösungen).

0 Stimmen

Auf welche Version welcher Python-Implementierung bezieht sich dies?

31voto

Tomer Gal Punkte 739

Python hat einen bitweisen Exklusiv-ODER-Operator, er heißt ^ :

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

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

bool(a) ^ bool(b)

(Bearbeitet - danke Arel)

1 Stimmen

Aus Ihrer Antwort sollte hervorgehen, dass ^ ist eine bitweise xor (nicht das logische xor, wie in der Frage angegeben). bool(2) ^ bool(3) gibt eine andere Antwort als bool(2 ^ 3) .

2 Stimmen

@Arel Aber das ist nicht der Fall. a ^ b ist polymorph. Wenn a et b son bool Instanzen, so lautet das Ergebnis bool auch. Dieses Verhalten kann kaum als "bitweises" xor bezeichnet werden.

0 Stimmen

@Alfe der wichtige Punkt ist, dass Werte müssen zuerst in Boolesche Werte umgewandelt werden. Die Python-Dokumentation definiert ^ als bitweise, auch wenn es ein interessanter Punkt ist, dass die Typen für bool et int Typen. Hinweis: True ^ 2 es 3 und zeigt damit, dass sie tatsächlich bitweise ist.

17voto

c z Punkte 6152

Einfach, leicht zu verstehen:

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

Wenn Sie eine exklusive Auswahl wünschen, d. h. wenn Sie 1 Auswahl aus n kann es auf mehrere Argumente erweitert werden:

sum(bool(x) for x in y) == 1

4 Stimmen

sum(map(bool, y)) % 2 == 1

1 Stimmen

Ich sehe wenig Grund für die Verwendung von sum wenn Sie nur 2 Variablen haben, bool(a) + bool(b) == 1 macht das Gleiche.

0 Stimmen

@Boris Potayto potarto

15voto

Arel Punkte 1222

Um das logische Xor von zwei oder mehr Variablen in Python zu erhalten:

  1. Eingaben in Boolesche Werte umwandeln
  2. Verwenden Sie den bitweisen Xor-Operator ( ^ o operator.xor )

Zum Beispiel,

bool(a) ^ bool(b)

Wenn Sie die Eingaben in Boolesche Werte umwandeln, bitweise xor wird logisch xor.

Beachten Sie, dass die akzeptierte Antwort falsch ist: != ist nicht dasselbe wie xor in Python wegen der Feinheiten von Operatorverkettung .

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

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

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

13voto

alan2here Punkte 2993

Vorausgesetzt, A und B sind bools.

A is not B

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