Jak uzyskać logiczny xor dwóch zmiennych w Pythonie?


647

Jak uzyskać logiczny xor dwóch zmiennych w Pythonie?

Na przykład mam dwie zmienne, które prawdopodobnie będą łańcuchami. Chcę przetestować, czy tylko jeden z nich zawiera wartość True (nie jest to None ani pusty ciąg znaków):

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

^Operator wydaje się być bitowe, a nie zdefiniowane na wszystkich obiektach:

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

3
Jak zdefiniujesz „xor” dla kilku ciągów? Jak myślisz, co „abc” ^ ”„ powinno zwrócić, że nie?
Mehrdad Afshari

18
Powinien zwracać wartość True, a nie zgłaszać wyjątek, ponieważ tylko jeden z ciągów znaków ma wartość True, zgodnie z definicją typu bool normalnego języka Python.
Zach Hirsch

38
Dziwi mnie, że Python nie ma operatora infix o nazwie „xor”, który byłby najbardziej intuicyjną implementacją w języku Python. Używanie „^” jest zgodne z innymi językami, ale nie jest tak rażąco czytelne, jak większość Pythona.
Mark E. Haase

13
@MehrdadAfshari Oczywistą odpowiedzią na twoje pytanie jest to, że a xor ajest zdefiniowane jako (a and not b) or (not a and b)i a xor bkiedy, ai kiedy bsą ciągami znaków lub jakimkolwiek innym typem, powinny dawać jakąkolwiek (a and not b) or (not a and b)wydajność.
Kaz

1
Problem polega na tym, że dokumentacja jest słaba. ^ jest „wyłączny bitowo lub”, co dosłownie interpretowane oznacza kawałek po bicie, a nie bool po bool. więc x'FFFF00 '^ x'FFFF00' powinno być x'000000 '. Czy może ma to nastąpić tylko na zasadzie char by char? rzucane jako liczby? Musimy iterować krótsze znaki ciągu, aby dopasować długość dłuższego ciągu. Wszystko to powinno być wbudowane.
mckenzm

Odpowiedzi:


1187

Jeśli już normalizujesz dane wejściowe do wartości logicznych, to! = Jest xor.

bool(a) != bool(b)

148
Chociaż jest to sprytne i krótkie, nie jestem przekonany, że jest czyste. Kiedy ktoś czyta ten konstrukt w kodzie, czy od razu jest dla niego oczywiste, że jest to operacja Xor? Czułem się zobowiązany do dodania komentarza - dla mnie znak, że piszę niejasny kod i próbuję przeprosić komentarzem.

47
Być może „czy jest jasne, że to XOR?” to złe pytanie. Próbowaliśmy tylko sprawdzić, czy odpowiedź na dwa pytania jest taka sama i myśląc, że użyjemy XOR, aby to zaimplementować. Na przykład, jeśli chcemy się upewnić, że nie porównujemy jabłek z pomarańczami, to „jeśli xor (isApple (x), isApple (y))” jest naprawdę wyraźniejsze niż „jeśli isApple (x)! = IsApple (y)”? Nie do mnie!
AmigoNico,

106
Wystąpił problem z użyciem „! =” Jako xor. Prawdopodobnie można oczekiwać, że bool (a)! = Bool (b)! = Bool (c) będzie taki sam jak bool (a) ^ bool (b) ^ bool (c). Więc rób casty, ale polecam ^. Aby dowiedzieć się, co się dzieje w pierwszym przykładzie, wyszukaj temat „Łączenie operatorów”.
elmo

19
@elmo: +1 za wskazanie różnicy i +1 za nauczenie mnie, czym jest łączenie operatorów! Jestem w obozie, który mówi, że! = Nie jest tak czytelny jak ^.
Mark E. Haase

13
powinno być bool(a) is not bool(b)zamiast tego?
RNA

485

Zawsze możesz użyć definicji xor, aby obliczyć ją na podstawie innych operacji logicznych:

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

Ale jest to dla mnie trochę zbyt szczegółowe i na pierwszy rzut oka nie jest szczególnie jasne. Innym sposobem na to jest:

bool(a) ^ bool(b)

Operator xor na dwóch boolach jest logicznym xor (w przeciwieństwie do ints, gdzie jest bitowy). To ma sens, ponieważ booljest tylko podklasąint , ale jest implementowane tak, aby zawierało tylko wartości 0i 1. Logiczny xor jest równoważny bitowemu xor, gdy domena jest ograniczona do 0i 1.

Tak więc logical_xorfunkcja zostanie zaimplementowana w następujący sposób:

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

Podziękowania dla Nicka Coghlana z listy mailingowej Python-3000 .


7
świetny post, ale ze wszystkich sposobów nazwania swoich parametrów, dlaczego „str1” i „str2”?
SingleNegationElimination

1
@Token, dlaczego nie. Masz na myśli to, że nie są bardzo Pythoniczne?
orokusaki

1
@Zach Hirsch Czy możesz użyć (nie a i b) zamiast (b i nie a) dla czytelności lub czy definicja byłaby niespójna z xor.
orokusaki

10
Powinieneś umieścić noty na pierwszym miejscu w taki (not b and a) or (not a and b)sposób, aby zwracał łańcuch, jeśli taki istnieje, co wydaje się pytonicznym sposobem działania funkcji.
rjmunro,

2
@TokenMacGuy: Co sugerowałeś, żeby zamiast tego nazwał je?
user541686

180

Bitowe wykluczanie - lub jest już wbudowane w Pythona, w operatormodule (który jest identyczny z ^operatorem):

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

3
Właśnie tego potrzebowałem. Podczas złośliwego oprogramowania do inżynierii odwrotnej wiele razy łańcuchy są zniekształcane aż do operacji XOR. Za pomocą tego chr (xor (ord ("n"), 0x1A)) = 't'
ril3y

75
Uważaj, to również bitowe: xor(1, 2)zwraca 3. Z dokumentacji: xor(a, b) -- Same as a ^ b. Pamiętaj, że wszystko, co importujesz, operatorjest po prostu funkcjonalną formą istniejącego wbudowanego operatora infix.
askewchan

5
@askewchan: booltyp przeciąża, __xor__aby zwrócić booleany. Będzie działać dobrze, ale jego przesada, kiedy bool(a) ^ bool(b)robi dokładnie to samo.
Martijn Pieters

@MartijnPieters ^Operator dzwoni __xor__wewnętrznie.
Quantum7

5
@ Quantum7: tak, nie jestem pewien, dlaczego mi to mówisz. Powiedziałem tylko, że ten booltyp implementuje __xor__metodę specjalnie, ponieważ ^ją wywołuje . Ponieważ wszystko bool(a) ^ bool(b)działa dobrze, nie ma potrzeby korzystania z tej operator.xor()funkcji.
Martijn Pieters

43

Jak wyjaśnił Zach , możesz użyć:

xor = bool(a) ^ bool(b)

Osobiście preferuję nieco inny dialekt:

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

Ten dialekt jest zainspirowany logicznym językiem diagramów, którego nauczyłem się w szkole, gdzie „OR” oznaczono ramką zawierającą ≥1(większą lub równą 1), a „XOR” oznaczono ramką zawierającą =1.

Ma to tę zaletę, że poprawnie implementuje wyłączne lub na wielu operandach.

  • „1 = a ^ b ^ c ...” oznacza, że ​​liczba prawdziwych operandów jest nieparzysta. Ten operator to „parzystość”.
  • „1 = a + b + c ...” oznacza, że ​​dokładnie jeden operand jest prawdziwy. Jest to „wyłączne lub”, co oznacza „jedno z wyłączeniem pozostałych”.

12
Tak więc True + True + False + True == 3 i 3! = 1, ale True XOR True XOR False XOR True == True. Czy potrafisz rozwinąć temat „prawidłowej implementacji XOR na wielu operandach”?
tzot

3
@tzot Twój przykład się nie udaje, ponieważ zgodnie z rozwiązaniem ddaa dodajesz dodatek tylko do dwóch zmiennych jednocześnie. Tak więc musiałby być właściwy sposób na napisanie tego wszystkiego (((((True + True)==1)+False)==1)+True)==1. Podana tutaj odpowiedź całkowicie uogólnia na wiele operandów.
ely

6
Ponadto istnieje różnica między trójstronnym XOR a zestawem dwóch XOR zgrupowanych według kolejności operacji. Zatem 3-WAY-XOR (A, B, C) to nie to samo, co XOR (XOR (A, B), C). I przykładem ddaa jest ten pierwszy, podczas gdy twój zakłada drugi.
ely

3
@ Mr.F Twoje wyjaśnienie tak naprawdę nie usprawiedliwia tej odpowiedzi. W Pythonie, jeśli tylko zrobić True + True + False + True, to nie dostać 3, i True + True + False + True == 3oddaje Truenatomiast True + True + False + True == 1oddaje False. Innymi słowy, odpowiedź tutaj nie uogólnia się poprawnie; aby to zrobić, musisz wykonać dodatkową pracę. Tymczasem prosty True ^ True ^ False ^ Truedziała zgodnie z oczekiwaniami.
jpmc26,

3
@ jpmc26 Nie rozumiem twojego komentarza. Podejście polegające na dodawaniu ma na celu uogólnienie operacji, w której chcesz sprawdzić, czy dokładnie jednym operandem jest Truewielorakie XOR. Jest to inna operacja niż na przykład A XOR B XOR ... XOR Z. Innymi słowy, jeśli planujesz użyć wersji opartej na dodawaniu, to po przesłaniu operandów True + True + False + Truepowinieneś spodziewać się, że wynik będzie Falsewiększy niż jeden z nich True, co działa, jeśli warunek zostanie sprawdzony == 1.
ely

26
  • Python logical or:: A or Bzwraca Ajeśli bool(A)jest True, w przeciwnym razie zwracaB
  • Python logical and:: A and Bzwraca Ajeśli bool(A)jest False, w przeciwnym razie zwracaB

Aby zachować większość tego sposobu myślenia, moją logiczną definicją xor byłoby:

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

W ten sposób może powrócić a, balbo False:

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

5
Wydaje mi się to złe, a przynajmniej dziwne. Żaden z innych wbudowanych operatorów logicznych nie zwraca jednej z trzech możliwych wartości.
Zach Hirsch,

2
@Zach Hirsch: Dlatego powiedziałem „zachować większość tego sposobu myślenia” - ponieważ nie ma dobrego wyniku, gdy oba są prawdziwe lub fałszywe
nosklo,

Operacja logiczna musi zwracać wartość logiczną, więc drugie „return a lub b” wygląda dziwnie, więc drugi zwrot musi zwracać True.
Denis Barmenkov

9
@Denis Barmenkov: Cóż, zauważ, że operatory logiczne python andi ornie zwrócą wartości logicznej. 'foo' and 'bar'zwraca 'bar'...
nosklo,

6
Na pierwszy rzut oka 2 poprzednie odpowiedzi wydają się najlepsze, ale po zastanowieniu, ta jest w rzeczywistości jedyną naprawdę poprawną, tj. Jedyną, która stanowi przykład xorimplementacji zgodnej z wbudowanym andi or. Jednak, oczywiście, w praktycznych sytuacjach, bool(a) ^ bool(b)a nawet a ^ b(jeśli ai bwiadomo, że są bool) są bardziej zwięzłe oczywiście.
Erik Kaplun

23

Przetestowałem kilka podejść i not a != (not b)okazało się, że jest najszybszy.

Oto kilka testów

%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

Edycja: W przykładach 1 i 3 powyżej brakuje nawiasów, więc wynik jest niepoprawny. Nowe wyniki + truth()funkcja, jak sugerował ShadowRanger.

%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

6
To 100 ns mojego życia nie wrócę ;-)
Arel

4
Aby uzyskać czas pomiędzy, możesz zrobić from operator import truthna górze modułu i przetestować truth(a) != truth(b). boolbycie konstruktor ma wiele nieuniknionych narzutu na poziomie C (musi przyjąć argumenty jako ekwiwalent *args, **kwargsi analizowania tuplei dictje wyodrębnić), gdzie truth(jest funkcją) można używać zoptymalizowaną ścieżką, która nie wymaga albo tuplealbo a dicti działa przez około połowę czasu boolrozwiązań opartych na rozwiązaniach (ale wciąż dłużej niż notrozwiązania oparte na rozwiązaniach).
ShadowRanger

9

Nagradzany wątek:

Pomysł anodera ... Wystarczy wypróbować (być może) pythonowe wyrażenie «nie», aby uzyskać zachowanie logicznego «xor»

Tabela prawdy wyglądałaby następująco:

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

A na przykład ciąg:

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

Jednak; jak wskazano powyżej, zależy to od faktycznego zachowania, które chcesz wyciągnąć z dowolnej pary ciągów, ponieważ ciągi nie są boleanami ... a nawet więcej: jeśli „Zanurzysz się w Pythonie”, znajdziesz „Osobliwą naturę” oraz „i” lub „» http://www.diveintopython.net/power_of_introspection/and_or.html

Przepraszam, mój napisany angielski, to nie jest mój urodzony język.

Pozdrowienia.


Używam również tego, aby odczytać to jako „zupełnie inny”. Jest tak, ponieważ niektóre języki używają do implementacji operacji krok po kroku reprezentacji binarnej i przyjmują bool wynikowej operacji bitowej. Wydaje mi się, że twoja odpowiedź jest bardziej „kuloodporna”, ponieważ wykracza poza przestrzeń logiczną.
yumper

Chodzi mi o to, że twoja odpowiedź obejmuje przypadek porównania None, False, ponieważ odmienne są rzeczy wyróżniające. Na przykład: bool (False)! = Bool (''), jednak False is not '' ”bardziej zgadza się z semantyką„ absolutnie innego ”
yumper

8

Python ma bitowo wyłączny operator OR, to ^:

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

Możesz go użyć, konwertując dane wejściowe na booleany przed zastosowaniem xor ( ^):

bool(a) ^ bool(b)

(Edytowane - dzięki Arel)


Twoja odpowiedź powinna wyjaśnić, że ^jest to bitowe xor (nie logiczne xor, takie jak zadane pytanie). bool(2) ^ bool(3)daje inną odpowiedź niż bool(2 ^ 3).
Arel

1
@Arel Ale tak nie jest. a ^ bjest polimorfem. Jeśli ai bboolinstancjami, wynik również będzie bool. Tego zachowania trudno nazwać „bitowym” xorem.
Alfe

@Ale ważne jest to, że najpierw należy rzutować wartości na logiczne. Dokumentacja Pythona jest zdefiniowana ^jako bitowa, mimo że interesujące jest zachowanie typów booli inttypów. Uwaga: True ^ 2to 3, co pokazuje, jak to rzeczywiście bitowe.
Arel

@Arel Tak, bool ^ intsprawa jest jak gdyby przerzucenie wszystkiego na intpierwszy plan . Mimo to, Python posiada wbudowaną w ^operatora dla wielu bitów inti na jeden bit reprezentowane w bool, więc oba są bitowe , ale bitowe xor dla pojedynczego bitu właśnie jest logiczny xor dla logicznych.
Alfe

Zawsze nienawidzę korzystać z tego operatora, chociaż rozumiem, że xorpochodzi on z inżynierii, więc instynktownie wydaje mi się matematyczną potęgą, 2^3 = pow(2,3)co oznacza, że ​​zawsze wyraźnie komentuję, aby zapobiec nieporozumieniom.
Nicholas Hamilton

8

Ponieważ nie widzę prostego wariantu xor wykorzystującego zmienne argumenty i tylko operację na wartościach Prawdy Prawda lub Fałsz, po prostu wyrzucę go tutaj, aby każdy mógł z niego skorzystać. Jest to, jak zauważają inni, dość (by nie powiedzieć bardzo) proste.

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

Użycie jest również proste:

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

Ponieważ jest to uogólniony n-ary logiczny XOR, jego wartość prawdy będzie Prawda za każdym razem, gdy liczba argumentów True będzie nieparzysta (i nie tylko wtedy, gdy dokładnie jeden jest Prawdą, to tylko jeden przypadek, w którym n-ary XOR jest Prawdą).

Dlatego jeśli szukasz predykatu n-ary, który ma wartość Prawda tylko wtedy, gdy jest dokładnie jeden z jego argumentów, możesz użyć:

def isOne(*vars):
    sum = False
    for v in vars:
        if sum and v:
            return False
        else:
            sum = sum or v
    return sum

Dla poprawy tej odpowiedzi: (bool(False) is False) == True. Możesz po prostu użyć Falsena tych liniach.
pathunstrom

7

Wyłączne lub jest zdefiniowane w następujący sposób

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

2
to zwróci True dla xor ('this', ')) i podążając drogą pythona, powinno zwrócić' this '.
nosklo

@nosklo: Weź to z BDFL, proszę, nie ja. Ponieważ Python zwraca True, musi to być sposób Pythona.
S.Lott

2
Mam na myśli spójność z innymi operatorami logicznymi Pythona - Python nie zwraca True, gdy to robię („to” lub „”), zwraca „to”. Ale w twojej funkcji xor („this”, ”) zwraca True. Powinien zwracać „to”, jak robi to wbudowane w Python lub „Python”.
nosklo

10
Python andi orwykonaj zwarcie. Żadna xorimplementacja nie może zwierać, więc istnieje już rozbieżność; dlatego nie ma powodu, xoraby działać tak jak and+ ordo.
tzot

7

Czasami pracuję z 1 i 0 zamiast boolowskich wartości True i False. W tym przypadku xor można zdefiniować jako

z = (x + y) % 2

który ma następującą tabelę prawdy:

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

7

Wiem, że jest późno, ale pomyślałem i może warto, tylko dla dokumentacji. Być może to zadziała: np.abs(x-y)pomysł jest taki

  1. jeśli x = prawda = 1, ay = fałsz = 0, to wynikiem będzie | 1-0 | = 1 = prawda
  2. jeśli x = False = 0, ay = False = 0, wynikiem będzie | 0-0 | = 0 = False
  3. jeśli x = prawda = 1, ay = prawda = 1, wówczas wynikiem będzie | 1-1 | = 0 = fałsz
  4. jeśli x = False = 0, ay = True = 1, wynikiem będzie | 0-1 | = 1 = True

7

Prosty, łatwy do zrozumienia:

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

Jeśli szukasz ekskluzywnego wyboru, możesz go rozszerzyć na wiele argumentów:

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

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

6

Co powiesz na to?

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

da, ajeśli bjest fałsz
, da, bjeśli ajest fałsz
, da Falseinaczej

Lub z wyrażeniem potrójnym Python 2.5+:

(False if a else b) if b else a

6

Niektóre sugerowane tutaj implementacje spowodują w niektórych przypadkach ponowną ocenę operandów, co może prowadzić do niezamierzonych efektów ubocznych i dlatego należy ich unikać.

Powiedział, że xorrealizacja który powraca albo Trueczy Falsejest dość prosta; jeden, który zwraca jeden z operandów, jeśli to możliwe, jest znacznie trudniejszy, ponieważ nie istnieje konsensus co do tego, który operand powinien być wybrany, zwłaszcza gdy są więcej niż dwa operandy. Na przykład, należy xor(None, -1, [], True)powrócić None, []albo False? Założę się, że każda odpowiedź wydaje się niektórym osobom najbardziej intuicyjna.

W przypadku wyniku True lub False istnieje aż pięć możliwych opcji: zwróć pierwszy operand (jeśli jest zgodny, wynikiem końcowym jest wartość, w przeciwnym razie boolean), zwróć pierwsze dopasowanie (jeśli przynajmniej jeden istnieje, boolean), zwraca ostatni argument (jeśli ... else ...), zwraca ostatni mecz (jeśli ... else ...) lub zawsze zwraca wartość logiczną. W sumie to 5 ** 2 = 25 smaków 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()

5

Wielu ludzi, w tym ja, potrzebuje xorfunkcji, która zachowuje się jak obwód xor wejściowy n, gdzie n jest zmienne. (Zobacz https://en.wikipedia.org/wiki/XOR_gate ). Implementuje to następująca prosta funkcja.

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)

Przykładowe I / O:

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

5

Aby uzyskać logiczny xor dwóch lub więcej zmiennych w Pythonie:

  1. Konwertuj dane wejściowe na logiczne
  2. Użyj bitowego operatora xor ( ^lub operator.xor)

Na przykład,

bool(a) ^ bool(b)

Podczas konwersji danych wejściowych na logiczne, bitowe xor staje się logicznym xor.

Zauważ, że zaakceptowana odpowiedź jest niepoprawna: != nie jest taka sama jak xor w Pythonie z powodu subtelności łączenia operatorów .

Na przykład xor trzech poniższych wartości jest niepoprawny podczas używania !=:

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

(PS Próbowałem edytować zaakceptowaną odpowiedź, aby uwzględnić to ostrzeżenie, ale moja zmiana została odrzucona).


4

Łatwo jest, gdy wiesz, co robi XOR:

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

4

Otrzymuje to logiczne wyłączne XOR dla dwóch (lub więcej) zmiennych

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

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

Pierwszym problemem związanym z tą konfiguracją jest to, że najprawdopodobniej przeszukuje całą listę dwa razy i przynajmniej sprawdzi co najmniej jeden z elementów dwa razy. Może to zwiększyć zrozumienie kodu, ale nie przyspiesza (co może nieznacznie różnić się w zależności od przypadku użycia).

Drugi problem z tym ustawieniem polega na tym, że sprawdza wyłączność niezależnie od liczby zmiennych. Z początku można to uznać za cechę, ale pierwszy problem staje się o wiele bardziej znaczący wraz ze wzrostem liczby zmiennych (jeśli kiedykolwiek tak się dzieje).


4

Xor jest ^w Pythonie. Zwraca:

  • Bitowe xor dla ints
  • Logiczne xor dla booli
  • Ekskluzywny związek dla zestawów
  • Zdefiniowane przez użytkownika wyniki dla klas, które implementują __xor__.
  • Błąd typu dla niezdefiniowanych typów, takich jak ciągi znaków lub słowniki.

Jeśli i tak zamierzasz używać ich na ciągach, rzutowanie ich boolsprawia, że ​​twoja operacja jest jednoznaczna (możesz także powiedzieć set(str1) ^ set(str2)).



3

W ten sposób kodowałbym każdą tabelę prawdy. W szczególności dla XOR mamy:

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

Wystarczy spojrzeć na wartości T w kolumnie odpowiedzi i połączyć razem wszystkie prawdziwe przypadki za pomocą logicznego lub. Tak więc ta tabela prawdy może zostać stworzona w przypadku 2 lub 3. Stąd,

xor = lambda a, b: (a and not b) or (not a and b)

-6

Możemy łatwo znaleźć xor dwóch zmiennych, używając:

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

Przykład:

xor (prawda, fałsz) >>> prawda


1
lub xor("hey", "there")>>> To prawda, ale nie tego chcemy
Mayou36,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.