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.

7voto

Steve L Punkte 1353

Manchmal ertappe ich mich dabei, dass ich mit 1 und 0 anstelle der booleschen Werte Wahr und Falsch arbeite. In diesem Fall kann xor definiert werden als

z = (x + y) % 2

die die folgende Wahrheitstabelle enthält:

     x
   |0|1|
  -+-+-+
  0|0|1|
y -+-+-+
  1|1|0|
  -+-+-+

7voto

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

Das heißt, ein xor Implementierung, die entweder True o False ist relativ einfach; eine, die einen der Operanden zurückgibt, wenn dies möglich ist, ist viel schwieriger, weil kein Konsens darüber besteht, welcher Operand der gewählte sein soll, insbesondere wenn es mehr als zwei Operanden gibt. Zum Beispiel, sollte xor(None, -1, [], True) return None , [] o False ? Ich wette, jede Antwort erscheint manchen Menschen als die intuitivste.

Für das Wahr- oder Falsch-Ergebnis gibt es bis zu fünf Möglichkeiten: erster Operand zurückgeben (wenn er mit dem Endergebnis im Wert übereinstimmt, sonst boolesch), erste Übereinstimmung zurückgeben (wenn mindestens eine vorhanden ist, sonst boolesch), letzter Operand zurückgeben (wenn ... sonst ...), letzte Übereinstimmung zurückgeben (wenn ... sonst ...), oder immer boolesch zurückgeben. Insgesamt sind das 5 ** 2 = 25 Varianten von 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()

7voto

S.Lott Punkte 371691

Exclusive Or ist wie folgt definiert

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

2 Stimmen

Das für xor('this', '') True zurückgeben würde, und um Python zu folgen, sollte es 'this' zurückgeben.

0 Stimmen

@nosklo: Wenden Sie sich bitte an den BDFL, nicht an mich. Da Python True zurückgibt, ist das muss der Weg von Python sein.

2 Stimmen

Ich meine aus Gründen der Konsistenz mit den anderen logischen Operatoren in Python - Python gibt nicht True zurück, wenn ich das tue ('this' oder ''), es gibt 'this' zurück. Aber in Ihrer Funktion gibt xor('this', '') True zurück. Es sollte 'this' zurückgeben, wie es das Python-Builtin "or" tut.

6voto

Arthur Hv Punkte 1391

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

  • Ein bitweises xor für Ints
  • Logisches xor für bools
  • Eine exklusive Vereinigung für Mengen
  • Benutzerdefinierte Ergebnisse für Klassen, die Folgendes implementieren __xor__ .
  • TypeError für undefinierte Typen, wie Strings oder Dictionaries.

Wenn Sie beabsichtigen, sie trotzdem auf Strings zu verwenden, sollten Sie sie in bool macht Ihren Vorgang eindeutig (Sie könnten auch meinen set(str1) ^ set(str2) ).

6voto

snagpaul Punkte 328

So würde ich jede Wahrheitstabelle kodieren. Für xor im Besonderen 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 fügen Sie alle wahren Fälle mit dem logischen oder zusammen. Diese Wahrheitstabelle kann also im Fall 2 oder 3 erzeugt werden. Daraus folgt,

xor = lambda a, b: (a and not b) or (not a and 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