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.

6voto

Markus Jarderot Punkte 83090

Wie wäre es damit?

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

wird geben a si b ist falsch
wird geben b si a ist falsch
wird geben False ansonsten

Oder mit dem ternären Ausdruck von Python 2.5+:

(False if a else b) if b else a

5voto

Marc Punkte 3685

Dies ergibt 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 dieser Vorgehensweise ist, dass die gesamte Liste höchstwahrscheinlich zweimal durchlaufen wird und mindestens eines der Elemente zweimal überprüft wird. Dadurch wird der Code zwar verständlicher, aber nicht schneller (was je nach Anwendungsfall vernachlässigbar sein kann).

Das zweite Problem bei dieser Vorgehensweise ist, dass unabhängig von der Anzahl der Variablen auf Ausschließlichkeit geprüft wird. Dies mag auf den ersten Blick als eine Besonderheit angesehen werden, aber das erste Problem wird mit zunehmender Anzahl der Variablen (wenn überhaupt) sehr viel bedeutender.

4voto

Denis Barmenkov Punkte 2300

Das ist einfach, wenn man weiß, was XOR macht:

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

2voto

mathandy Punkte 1362

Das ist eine Verallgemeinerung.

def xor(*orands):
    return sum(bool(x) for x in orands) == 1

Sie können es testen mit

# test
from itertools import product
for a, b, c in product((False, True), repeat=3):
    print(f'{int(a)}{int(b)}{int(c)}|{xor(a,b,c)}')

Ausgabe:

000|Falsch
001|Wahr
010|Wahr
011|Falsch
100|Wahr
101|Falsch
110|Falsch
111|Falsch

1voto

GdV Punkte 21

Nur weil ich nicht gesehen habe, dass es anderswo erwähnt wird, ist dies auch der Trick:

def logical_xor(a, b):
    return not b if a else bool(b)

Ich bin nicht sicher, ob das "besser"/lesbarer/pythonischer ist als die akzeptierte Lösung bool(a) != bool(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