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'
python
logical-operators
Zach Hirsch
źródło
źródło
a xor a
jest zdefiniowane jako(a and not b) or (not a and b)
ia xor b
kiedy,a
i kiedyb
są ciągami znaków lub jakimkolwiek innym typem, powinny dawać jakąkolwiek(a and not b) or (not a and b)
wydajność.Odpowiedzi:
Jeśli już normalizujesz dane wejściowe do wartości logicznych, to! = Jest xor.
źródło
bool(a) is not bool(b)
zamiast tego?Zawsze możesz użyć definicji xor, aby obliczyć ją na podstawie innych operacji logicznych:
Ale jest to dla mnie trochę zbyt szczegółowe i na pierwszy rzut oka nie jest szczególnie jasne. Innym sposobem na to jest:
Operator xor na dwóch boolach jest logicznym xor (w przeciwieństwie do ints, gdzie jest bitowy). To ma sens, ponieważ
bool
jest tylko podklasąint
, ale jest implementowane tak, aby zawierało tylko wartości0
i1
. Logiczny xor jest równoważny bitowemu xor, gdy domena jest ograniczona do0
i1
.Tak więc
logical_xor
funkcja zostanie zaimplementowana w następujący sposób:Podziękowania dla Nicka Coghlana z listy mailingowej Python-3000 .
źródło
(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.Bitowe wykluczanie - lub jest już wbudowane w Pythona, w
operator
module (który jest identyczny z^
operatorem):źródło
xor(1, 2)
zwraca3
. Z dokumentacji:xor(a, b) -- Same as a ^ b.
Pamiętaj, że wszystko, co importujesz,operator
jest po prostu funkcjonalną formą istniejącego wbudowanego operatora infix.bool
typ przeciąża,__xor__
aby zwrócić booleany. Będzie działać dobrze, ale jego przesada, kiedybool(a) ^ bool(b)
robi dokładnie to samo.^
Operator dzwoni__xor__
wewnętrznie.bool
typ implementuje__xor__
metodę specjalnie, ponieważ^
ją wywołuje . Ponieważ wszystkobool(a) ^ bool(b)
działa dobrze, nie ma potrzeby korzystania z tejoperator.xor()
funkcji.Jak wyjaśnił Zach , możesz użyć:
Osobiście preferuję nieco inny dialekt:
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.
źródło
(((((True + True)==1)+False)==1)+True)==1
. Podana tutaj odpowiedź całkowicie uogólnia na wiele operandów.True + True + False + True
, to nie dostać3
, iTrue + True + False + True == 3
oddajeTrue
natomiastTrue + True + False + True == 1
oddajeFalse
. Innymi słowy, odpowiedź tutaj nie uogólnia się poprawnie; aby to zrobić, musisz wykonać dodatkową pracę. Tymczasem prostyTrue ^ True ^ False ^ True
działa zgodnie z oczekiwaniami.True
wielorakie XOR. Jest to inna operacja niż na przykładA XOR B XOR ... XOR Z
. Innymi słowy, jeśli planujesz użyć wersji opartej na dodawaniu, to po przesłaniu operandówTrue + True + False + True
powinieneś spodziewać się, że wynik będzieFalse
większy niż jeden z nichTrue
, co działa, jeśli warunek zostanie sprawdzony== 1
.or
::A or B
zwracaA
jeślibool(A)
jestTrue
, w przeciwnym razie zwracaB
and
::A and B
zwracaA
jeślibool(A)
jestFalse
, w przeciwnym razie zwracaB
Aby zachować większość tego sposobu myślenia, moją logiczną definicją xor byłoby:
W ten sposób może powrócić
a
,b
alboFalse
:źródło
and
ior
nie zwrócą wartości logicznej.'foo' and 'bar'
zwraca'bar'
...xor
implementacji zgodnej z wbudowanymand
ior
. Jednak, oczywiście, w praktycznych sytuacjach,bool(a) ^ bool(b)
a naweta ^ b
(jeślia
ib
wiadomo, że sąbool
) są bardziej zwięzłe oczywiście.Przetestowałem kilka podejść i
not a != (not b)
okazało się, że jest najszybszy.Oto kilka testów
Edycja: W przykładach 1 i 3 powyżej brakuje nawiasów, więc wynik jest niepoprawny. Nowe wyniki +
truth()
funkcja, jak sugerował ShadowRanger.źródło
from operator import truth
na górze modułu i przetestowaćtruth(a) != truth(b)
.bool
bycie konstruktor ma wiele nieuniknionych narzutu na poziomie C (musi przyjąć argumenty jako ekwiwalent*args, **kwargs
i analizowaniatuple
idict
je wyodrębnić), gdzietruth
(jest funkcją) można używać zoptymalizowaną ścieżką, która nie wymaga albotuple
albo adict
i działa przez około połowę czasubool
rozwiązań opartych na rozwiązaniach (ale wciąż dłużej niżnot
rozwiązania oparte na rozwiązaniach).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:
A na przykład ciąg:
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.
źródło
Python ma bitowo wyłączny operator OR, to
^
:Możesz go użyć, konwertując dane wejściowe na booleany przed zastosowaniem xor (
^
):(Edytowane - dzięki Arel)
źródło
^
jest to bitowe xor (nie logiczne xor, takie jak zadane pytanie).bool(2) ^ bool(3)
daje inną odpowiedź niżbool(2 ^ 3)
.a ^ b
jest polimorfem. Jeślia
ib
sąbool
instancjami, wynik również będziebool
. Tego zachowania trudno nazwać „bitowym” xorem.^
jako bitowa, mimo że interesujące jest zachowanie typówbool
iint
typów. Uwaga:True ^ 2
to3
, co pokazuje, jak to rzeczywiście bitowe.bool ^ int
sprawa jest jak gdyby przerzucenie wszystkiego naint
pierwszy plan . Mimo to, Python posiada wbudowaną w^
operatora dla wielu bitówint
i na jeden bit reprezentowane wbool
, więc oba są bitowe , ale bitowe xor dla pojedynczego bitu właśnie jest logiczny xor dla logicznych.xor
pochodzi 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.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.
Użycie jest również proste:
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ć:
źródło
(bool(False) is False) == True
. Możesz po prostu użyćFalse
na tych liniach.Wyłączne lub jest zdefiniowane w następujący sposób
źródło
and
ior
wykonaj zwarcie. Żadnaxor
implementacja nie może zwierać, więc istnieje już rozbieżność; dlatego nie ma powodu,xor
aby działać tak jakand
+or
do.Czasami pracuję z 1 i 0 zamiast boolowskich wartości True i False. W tym przypadku xor można zdefiniować jako
który ma następującą tabelę prawdy:
źródło
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źródło
Prosty, łatwy do zrozumienia:
Jeśli szukasz ekskluzywnego wyboru, możesz go rozszerzyć na wiele argumentów:
źródło
sum(map(bool, y)) % 2 == 1
Co powiesz na to?
da,
a
jeślib
jest fałsz, da,
b
jeślia
jest fałsz, da
False
inaczejLub z wyrażeniem potrójnym Python 2.5+:
źródło
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
xor
realizacja który powraca alboTrue
czyFalse
jest 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żyxor(None, -1, [], True)
powrócićNone
,[]
alboFalse
? 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
.źródło
Wielu ludzi, w tym ja, potrzebuje
xor
funkcji, 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.Przykładowe I / O:
źródło
Aby uzyskać logiczny xor dwóch lub więcej zmiennych w Pythonie:
^
luboperator.xor
)Na przykład,
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
!=
:(PS Próbowałem edytować zaakceptowaną odpowiedź, aby uwzględnić to ostrzeżenie, ale moja zmiana została odrzucona).
źródło
Łatwo jest, gdy wiesz, co robi XOR:
źródło
Otrzymuje to logiczne wyłączne XOR dla dwóch (lub więcej) zmiennych
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).
źródło
Xor jest
^
w Pythonie. Zwraca:__xor__
.Jeśli i tak zamierzasz używać ich na ciągach, rzutowanie ich
bool
sprawia, że twoja operacja jest jednoznaczna (możesz także powiedziećset(str1) ^ set(str2)
).źródło
XOR jest zaimplementowany w
operator.xor
.źródło
W ten sposób kodowałbym każdą tabelę prawdy. W szczególności dla XOR mamy:
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,
źródło
Możemy łatwo znaleźć xor dwóch zmiennych, używając:
Przykład:
źródło
xor("hey", "there")
>>> To prawda, ale nie tego chcemy