Как получить логический xor двух переменных в Python?
Например, у меня есть две переменные, которые я ожидаю быть строками. Я хочу проверить, что только один из них содержит значение True (не None и не пустая строка):
str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
if logical_xor(str1, str2):
print "ok"
else:
print "bad"
Оператор ^ кажется побитовым и определен не для всех объектов:
>>> 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'
Он должен возвращать True, а не вызывать исключение, поскольку только одна из строк имеет значение True, как определено обычным типом Python bool.
Я удивлен, что в Python нет инфиксного оператора под названием «xor», который был бы наиболее интуитивно понятной реализацией Pythonic. Использование «^» согласуется с другими языками, но не так очевидно читаемо, как большинство Python.
@MehrdadAfshari Очевидный ответ на ваш вопрос заключается в том, что a xor a определяется как (a and not b) or (not a and b), и поэтому a xor b, когда a и b являются символьными строками или любыми другими типами, должен давать все, что дает (a and not b) or (not a and b).
Проблема в том, что документация оставляет желать лучшего. ^ - это «побитовое исключающее ИЛИ», которое буквально интерпретируется как бит за битом, а не bool за bool. поэтому x'FFFF00 '^ x'FFFF00' должно быть x'000000 '. Или это должно происходить только по символам? преобразовать в числа? Нам нужно перебирать символы более короткой строки, чтобы она соответствовала длине более длинной строки. Все это должно быть встроено.






Вы всегда можете использовать определение xor, чтобы вычислить его из других логических операций:
(a and not b) or (not a and b)
Но для меня это слишком многословно и на первый взгляд не очень понятно. Другой способ сделать это:
bool(a) ^ bool(b)
Оператор xor для двух логических значений является логическим xor (в отличие от int, где он побитовый). Это имеет смысл, поскольку bool - это просто подкласс int, но реализовано только для значений 0 и 1. И логический xor эквивалентен поразрядному xor, когда домен ограничен 0 и 1.
Таким образом, функция logical_xor будет реализована следующим образом:
def logical_xor(str1, str2):
return bool(str1) ^ bool(str2)
Кредит для Ник Коглан в списке рассылки Python-3000.
отличный пост, но из всех способов назвать ваши параметры, почему 'str1' и 'str2'?
@Token, почему бы и нет. Вы имеете в виду, потому что они не очень питонические?
@orokusaki: потому что они, кажется, не очень хорошо предлагают предполагаемое использование.
@Zach Hirsch Не могли бы вы использовать (не a и b) вместо (b, а не a) для удобства чтения, или определение будет несовместимо с xor.
Вы должны сначала поставить nots, как этот (not b and a) or (not a and b), чтобы он возвращал строку, если она есть, что похоже на питонический способ работы функции.
@TokenMacGuy: Что вы предлагали ему вместо этого назвать их?
Я думал о том, чтобы сказать что-то о том, что оба входа вызываются перед вызовом функции (что часто является недостатком реализации ваших собственных логических функций), но потом я вспомнил, что xor все равно не может закоротить. Вы можете записать это.
Ваш ответ bool(a) ^ bool(b) гораздо яснее показывает намерение программиста xor, чем принятый в настоящее время ответ bool(a) != bool(b).
or: A or B: возвращает A, если bool(A) - это True, в противном случае возвращает Band: A and B: возвращает A, если bool(A) - это False, в противном случае возвращает BЧтобы сохранить большую часть этого образа мышления, мое логическое определение xor будет следующим:
def logical_xor(a, b):
if bool(a) == bool(b):
return False
else:
return a or b
Таким образом он может вернуть a, b или False:
>>> logical_xor('this', 'that')
False
>>> logical_xor('', '')
False
>>> logical_xor('this', '')
'this'
>>> logical_xor('', 'that')
'that'
Мне это кажется плохим или, по крайней мере, странным. Ни один из других встроенных логических операторов не возвращает одно из трех возможных значений.
@ Zach Hirsch: Вот почему я сказал «сохранить наиболее такого образа мышления» - поскольку нет хорошего результата, когда оба истинны или ложны.
Логическая операция должна возвращать логическое значение, поэтому второе «return a или b» выглядит странно, поэтому второе return должно возвращать True.
@ Денис Барменков: Обратите внимание, что логические операторы Python and и or не возвращают логическое значение. 'foo' and 'bar' возвращает 'bar' ...
На первый взгляд, два предыдущих ответа кажутся лучшими, но, если подумать, этот на самом деле единственный действительно правильный, то есть единственный, который предоставляет пример реализации xor, совместимой со встроенным and. и or. Однако, конечно, в практических ситуациях bool(a) ^ bool(b) или даже a ^ b (если известно, что a и b являются bool), конечно, более лаконичны.
Исключительное ИЛИ определяется следующим образом
def xor( a, b ):
return (a or b) and not (a and b)
который вернет True для xor ('this', '') и, чтобы следовать путем python, он должен вернуть 'this'.
@nosklo: Обсуди это с BDFL, пожалуйста, не я. Поскольку Python возвращает True, то должен будет способом Python.
Я имею в виду согласованность с другими логическими операторами python - Python не возвращает True, когда я это делаю ('this' или ''), он возвращает 'this'. Но в вашей функции xor ('this', '') возвращает True. Он должен возвращать this, как и встроенная функция python.
Python and и or делают короткое замыкание. Любая реализация xor не может замыкать накоротко, так что несоответствие уже есть; следовательно, нет причин, по которым xor должен работать так же, как and + or.
Как объяснил Зак, вы можете использовать:
xor = bool(a) ^ bool(b)
Лично я предпочитаю немного другой диалект:
xor = bool(a) + bool(b) == 1
Этот диалект основан на языке логических диаграмм, который я изучал в школе, где «ИЛИ» обозначалось прямоугольником, содержащим ≥1 (больше или равно 1), а «XOR» обозначалось прямоугольником, содержащим =1.
Это дает преимущество правильной реализации исключительного или нескольких операндов.
Итак, True + True + False + True == 3 и 3! = 1, но True XOR True XOR False XOR True == True. Не могли бы вы подробнее рассказать о «правильной реализации XOR для нескольких операндов»?
@ ΩΤΖΙΟΥ: завернуть в bool()
@tzot Ваш пример не работает, потому что, согласно решению ddaa, вы применяете добавление только к двум переменным за раз. Так что правильный способ записать все это должен быть (((((True + True)==1)+False)==1)+True)==1. Приведенный здесь ответ полностью обобщается на несколько операндов.
Кроме того, существует разница между трехсторонним XOR и набором из двух XOR, сгруппированных по порядку операций. Итак, 3-WAY-XOR (A, B, C) - это нет, то же самое, что XOR (XOR (A, B), C). И пример ddaa - первое, а ваш - второе.
@EMS: спасибо. Ваши возражения прояснили (для меня), что означает ddaa.
@ Mr.F Ваше объяснение не оправдывает этот ответ. В Python, если вы просто выполняете True + True + False + True, вы делать получаете 3, а True + True + False + True == 3 возвращает True, а True + True + False + True == 1 возвращает False. Другими словами, ответ здесь неверен; для этого вам необходимо проделать дополнительную работу. Между тем, простой True ^ True ^ False ^ True работает как положено.
@ jpmc26 Я не понимаю вашего комментария. Подход сложения предназначен для обобщения операции, в которой вы хотите проверить, что операндом ровно один является True, множественное исключающее ИЛИ. Это другая операция, чем, например, A XOR B XOR ... XOR Z. Другими словами, если вы планируете использовать версию, основанную на сложении, то после отправки операндов в True + True + False + True вы должны ожидать, что результатом будет False, поскольку более чем один из них - это True, который работает, если условие проверяет наличие == 1.
Поэтому, когда вы пишете True + True + False + True == 1, возвращает False, что является правильным и желательным, если вы используете подход сложения. Возможно, я неправильно понимаю вашу точку зрения, но я не вижу, что не так. Ему решать, хочет ли человек ту или иную операцию, а для множественного XOR, это просто вопрос семантики, какая из этих операций «является XOR».
(bool (a) + bool (b) + bool (c))% 2 == 1 будет работать, но ^-ing не стоит.
Гарантирует ли язык, что bool (a) ^ bool (b) будет bool (а не просто int)? Если да, то где документально подтверждена гарантия? Спасибо.
@ddaa Не понимаю почему. Это очень важно для вашего первого предложенного ответа.
@ddaa Скажем так, это предположение, воплощенное в текущем поведении CPython. Я просто спрашиваю, знаете ли вы, какой тип будет возвращен вашим первым предложенным ответом в любой действующей реализации Python. Это простой вопрос, даже если у вас есть какое-то личное отвращение к is.
Вы предполагаете, что существует такая вещь, как «допустимая реализация Python». Насколько я знаю, такого не существует. Поэтому ваш вопрос недействителен.
Действительно есть. Вот почему вы можете запускать одну и ту же программу Python на нескольких по-разному реализованных интерпретаторах.
Как насчет этого?
(not b and a) or (not a and b)
выдаст a, если b ложный
выдаст b, если a ложно
даст False в противном случае
Или с троичным выражением Python 2.5+:
(False if a else b) if b else a
Если вы уже нормализуете входные данные до логических значений, то! = - это xor.
bool(a) != bool(b)
Хотя это умно и коротко, я не уверен, что это чисто. Когда кто-то читает эту конструкцию в коде, становится ли им сразу очевидно, что это операция xor? Я чувствовал себя обязанным добавить комментарий - знак для меня, что я пишу нечеткий код и пытаюсь извиниться с помощью комментария.
Возможно, «ясно, что это XOR?» это неправильный вопрос. Мы просто пытались увидеть, одинаковы ли ответы на два вопроса, и думали, что будем использовать XOR для реализации этого. Например, если мы хотим убедиться, что мы не сравниваем яблоки с апельсинами, будет ли «if xor (isApple (x), isApple (y))» действительно яснее, чем «if isApple (x)! = IsApple (y)»? Не для меня!
Возникла проблема с использованием "! = " В качестве xor. Вы, вероятно, ожидаете, что bool (a)! = Bool (b)! = Bool (c) будет таким же, как bool (a) ^ bool (b) ^ bool (c). Так что делайте приведение в bool, но я бы порекомендовал ^. Чтобы узнать, что происходит в первом примере, найдите «цепочка операторов».
@elmo: +1 за указание на разницу и +1 за то, что научил меня, что такое цепочка операторов! Я нахожусь в лагере, который говорит, что! = Не так читается, как ^.
Просто совет для таких простодушных, как я: будьте осторожны с приоритетом операторов! Я хотел проверить, обе ли две переменные равны нулю или обе не равны нулю, и в итоге написал (a is None != b is None). Что ж, это неправильно!
вместо этого должен быть bool(a) is not bool(b)?
Это настоящий ответ? Я пробую этот код на своей машине, print bool("Hellow World") == bool("H"), он возвращает True
@Jason Вы используете == вместо !=. При необходимости можно проверить перебором: for b1, b2 in ((True, False), (True, True), (False, False): assert (b1 != b2) == (b1 ^ b1). Это проверка по таблице истинности (с учетом коммутативности оператора). Я оставлю это как упражнение для проверки с помощью правил вывода;)
Мало того, что это затрудняет понимание кода, как указывает @elmo, это НЕ эквивалентно операции xor и может привести к трудно обнаруживаемым ошибкам в коде. operator.xor будет лучшей альтернативой.
Голосование вниз, потому что этот ответ НЕПРАВИЛЬНЫЙ (поскольку, как указано @elmo !=, не является XOR в python)
@Arel: Для bool, для единственного сравнения, != точно такой же, как xor. Это только для связанного случая, когда поведение отличается. Не стоит отрицать.
@ShadowRanger xor (^) - это xor. Не-равно (!=) не является xor в Python по тонкой причине, которая могла быть разъяснена в ответе, но не была. Вы правы, что он работает в случае с двумя переменными, как задается вопрос, но утверждение, что != является xor, неточно и ненужно. Я пытался отредактировать этот вопрос (дважды), чтобы добавить пояснение, но рецензенты отклонили мои изменения. Следовательно, голос против.
Зачем обвинять респондента в плохих рецензентах?
@RNA Нет, не сравнивайте логические значения с is. Этот ответ объясняет, почему во втором разделе. PEP 8 также упоминает об этом, но не объясняет.
@wjandrea Этот пост кажется неполным для bool(x) is True. Мы можем быть уверены, что значение, возвращаемое bool, будет либо True, либо False.
@Josiah Да, но мы не можем быть уверены, что True is True, потому что это деталь реализации.
@wjandrea True is True - это гарантировано справочником по языку Python. Спасибо, Педро, за вопрос
@Josiah О, да, ответ, который я связал, должен быть неправильным или устаревшим. Тем не менее, сравнение на равенство более интуитивно понятно, чем сравнение идентичности, хотя они делают то же самое для двух bool.
Некоторые из предложенных здесь реализаций в некоторых случаях вызовут повторную оценку операндов, что может привести к непреднамеренным побочным эффектам, и поэтому их следует избегать.
Тем не менее, реализация xor, которая возвращает либо True, либо False, довольно проста; тот, который возвращает один из операндов, если это возможно, намного сложнее, потому что не существует консенсуса относительно того, какой операнд следует выбрать, особенно когда имеется более двух операндов. Например, должен ли xor(None, -1, [], True) возвращать None, [] или False? Готов поспорить, каждый ответ кажется некоторым людям наиболее интуитивно понятным.
Для истинного или ложного результата существует до пяти возможных вариантов: вернуть первый операнд (если он соответствует конечному результату по значению, иначе логическое значение), вернуть первое совпадение (если хотя бы один существует, иначе логическое значение), возвращать последний операнд (если ... еще ...), возвращать последнее совпадение (если ... еще ...) или всегда возвращать логическое значение. В целом, это 5 ** 2 = 25 вкусов 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()
Поскольку я не вижу простого варианта xor, использующего переменные аргументы и только операции со значениями истины True или False, я просто добавлю его сюда, чтобы любой мог использовать. Как отмечают другие, довольно (чтобы не сказать очень) просто.
def xor(*vars):
result = False
for v in vars:
result = result ^ bool(v)
return result
И использование также простое:
if xor(False, False, True, False):
print "Hello World!"
Поскольку это обобщенный n-арный логический XOR, его истинное значение будет True всякий раз, когда количество истинных операндов нечетное (и не только когда точно один из них истинен, это всего лишь один случай, когда n-арное XOR имеет значение True).
Таким образом, если вы ищете n-арный предикат, который является истинным только тогда, когда равен ровно один из его операндов, вы можете использовать:
def isOne(*vars):
result = False
for v in vars:
if result and v:
return False
else:
result = result or v
return result
Для улучшения этого ответа: (bool(False) is False) == True. Вы можете просто использовать False в этих строках.
Это легко, когда вы знаете, что делает 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))
XOR реализован в operator.xor.
operator.xor соответствует побитовой операции, которая не нужна исходному плакату.
@kojiro видимо так!
Побитовое исключающее ИЛИ уже встроено в Python в модуле operator (который идентичен оператору ^):
from operator import xor
xor(bool(a), bool(b)) # Note: converting to bools is essential
Это то, что мне было нужно. При обратном проектировании вредоносного ПО много раз строки искажаются до операции XOR. Используя это chr (xor (ord ("n"), 0x1A)) = 't'
Будьте осторожны, это тоже побитовое: xor(1, 2) возвращает 3. Из строки документации: xor(a, b) -- Same as a ^ b. Помните, что все, что импортировано из operator, является просто функциональной формой существующего встроенного инфиксного оператора.
@askewchan: Тип bool перегружает __xor__ для возврата логических значений. Он будет работать нормально, но когда bool(a) ^ bool(b) делает то же самое, это перебор.
@MartijnPieters Оператор ^ вызывает внутренний вызов __xor__.
@ Quantum7: да, я не совсем понимаю, почему вы мне это говорите. Я только что сказал, что тип bool реализует метод __xor__особенно потому, что ^ называет это. Дело в том, что bool(a) ^ bool(b) работает нормально, здесь нет необходимости использовать функцию operator.xor().
Иногда я обнаруживаю, что работаю с 1 и 0 вместо логических значений True и False. В этом случае xor можно определить как
z = (x + y) % 2
который имеет следующую таблицу истинности:
x
|0|1|
-+-+-+
0|0|1|
y -+-+-+
1|1|0|
-+-+-+
Это получает логический исключающий XOR для двух (или более) переменных.
str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
any([str1, str2]) and not all([str1, str2])
Первая проблема с этой настройкой заключается в том, что она, скорее всего, дважды просматривает весь список и, как минимум, дважды проверяет хотя бы один из элементов. Таким образом, это может улучшить понимание кода, но не увеличивает скорость (которая может незначительно отличаться в зависимости от вашего варианта использования).
Вторая проблема с этой настройкой заключается в том, что она проверяет исключительность независимо от количества переменных. Поначалу это можно рассматривать как особенность, но первая проблема становится намного более значимой по мере увеличения числа переменных (если они вообще когда-либо появляются).
Я протестировал несколько подходов, и not a != (not b) оказался самым быстрым.
Вот несколько тестов
%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
Редактировать:
В примерах 1 и 3 выше скобки отсутствуют, поэтому результат неверен. Новые результаты + функция truth(), как предложил 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
Я не верну 100 нс моей жизни ;-)
Для промежуточной синхронизации вы можете сделать from operator import truth в верхней части модуля и протестировать truth(a) != truth(b). bool, будучи конструктором, имеет много неизбежных накладных расходов на уровне C (он должен принимать аргументы как эквивалент *args, **kwargs и анализировать tuple и dict для их извлечения), где truth (будучи функцией) может использовать оптимизированный путь, который не Они требуют либо tuple, либо dict, и работают примерно в два раза быстрее, чем решения на основе bool (но все же дольше, чем решения на основе not).
Награждение ветки:
Идея Anoder ... Просто попробуйте (может быть) питоническое выражение «is not», чтобы получить поведение логического «xor».
Таблица истинности будет такой:
>>> True is not True
False
>>> True is not False
True
>>> False is not True
True
>>> False is not False
False
>>>
И для вашей примерной строки:
>>> "abc" is not ""
True
>>> 'abc' is not 'abc'
False
>>> 'abc' is not ''
True
>>> '' is not 'abc'
True
>>> '' is not ''
False
>>>
Тем не мение; как они указали выше, это зависит от фактического поведения, которое вы хотите извлечь для любой пары строк, потому что строки не являются болеанами ... и даже больше: если вы «Dive Into Python», вы найдете «Своеобразную природу» и "и" или "» http://www.diveintopython.net/power_of_introspection/and_or.html
Извините, мой письменный английский, это не мой родной язык.
С Уважением.
Я также использую, чтобы читать это как «строго другое». Это потому, что некоторые языки используют для побитовой реализации операции двоичного представления и принимают логическое значение результирующей побитовой операции. Думаю, ваш ответ более «пуленепробиваемый», потому что он выходит за рамки логического пространства.
Я имею в виду тот факт, что ваш ответ касается случая сравнения None, False '', поскольку различие - это отличительный материал. Например: bool (False)! = Bool (''), тем не менее, False не '' "больше согласуется с семантикой" строго различного "
Я знаю, что это поздно, но у меня была мысль, и, возможно, это того стоит, просто для документации. Возможно, это сработает: np.abs(x-y) Идея в том, что
Вы даже можете отказаться от abs, python интерпретирует отрицательные числа как правду, хотя это очень непонятно, imo (что означает if (x > 1) - (y > 3)?
Просто, понятно:
sum(bool(a), bool(b)) == 1
Если вам нужен эксклюзивный выбор, то есть выбрать вариант 1 из n, его можно расширить до нескольких аргументов:
sum(bool(x) for x in y) == 1
sum(map(bool, y)) % 2 == 1Я не вижу смысла использовать sum, если у вас всего две переменные, bool(a) + bool(b) == 1 делает то же самое.
Мы можем легко найти xor двух переменных, используя:
def xor(a,b):
return a !=b
Пример:
xor(True,False) >>> True
или xor("hey", "there") >>> Верно, но мы этого не хотим
Xor - это ^ в Python. Он возвращает:
__xor__.Если вы все равно собираетесь использовать их в строках, приведение их к bool сделает вашу операцию однозначной (вы также можете иметь в виду set(str1) ^ set(str2)).
Многим, в том числе и мне, нужна функция xor, которая ведет себя как схема xor с n входами, где n - переменная. (См. https://en.wikipedia.org/wiki/XOR_gate). Это реализует следующая простая функция.
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)
Ниже приводится пример ввода / вывода:
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
В Python есть побитовый оператор исключающего ИЛИ, это ^:
>>> True ^ False
True
>>> True ^ True
False
>>> False ^ True
True
>>> False ^ False
False
Вы можете использовать его, преобразовав входные данные в логические перед применением xor (^):
bool(a) ^ bool(b)
(Отредактировано - спасибо Арел)
В вашем ответе должно быть ясно, что ^ - это xor побитовый (не логический xor, как заданный вопрос). bool(2) ^ bool(3) дает другой ответ, чем bool(2 ^ 3).
@Arel Но это не так. a ^ b является полиморфом. Если a и b являются экземплярами bool, результатом также будет bool. Такое поведение сложно назвать «побитовым» xor.
@Alfe важным моментом является то, что значения должны быть сначала преобразованы в логические. Документация Python определяет ^ как побитовое, хотя интересно, что типы сохраняются для типов bool и int. Примечание: True ^ 2 - это 3, демонстрируя, как это действительно поразрядно.
@Arel Да, корпус bool ^ int в первую очередь перекладывает все на int. Тем не менее, Python имеет встроенный оператор ^ для многих битов в int и для одного бита, представленного в bool, так что оба являются побитовый, но побитовый xor для одного бита просто является xor логичный для логических значений.
Я всегда ненавижу использовать этот оператор, хотя я понимаю, что это xor, из инженерного опыта, мне это инстинктивно кажется математической силой, то есть 2^3 = pow(2,3), что означает, что я всегда прямо комментирую, чтобы избежать путаницы.
Чтобы получить логический xor двух или более переменных в Python:
^ или operator.xor)Например,
bool(a) ^ bool(b)
Когда вы конвертируете входные данные в логические, побитовый xor становится логичный xor.
Обратите внимание, что принятый ответ неверен:!= не то же самое, что xor в Python из-за тонкости цепочка операторов.
Например, xor трех приведенных ниже значений неверен при использовании !=:
True ^ False ^ False # True, as expected of XOR
True != False != False # False! Equivalent to `(True != False) and (False != False)`
(P.S. Я попытался отредактировать принятый ответ, чтобы включить это предупреждение, но мое изменение было отклонено.)
Вот как я бы кодировал любую таблицу истинности. В частности, для xor у нас есть:
| a | b | xor | |
|---|----|-------|-------------|
| T | T | F | |
| T | F | T | a and not b |
| F | T | T | not a and b |
| F | F | F | |
Просто посмотрите на значения T в столбце ответов и объедините все истинные случаи логическим или. Итак, эта таблица истинности может быть получена в случае 2 или 3. Следовательно,
xor = lambda a, b: (a and not b) or (not a and b)
def xor(*args):
return sum(bool(arg) for arg in args)%2
если вы хотите только одну истину:
def onlyOne(*args):
return sum(bool(arg) for arg in args)==1
Это не xor, когда len(args) больше 2
Способ, которым Python обрабатывает логические операции, может сбивать с толку, поэтому моя реализация дает пользователю возможность (по умолчанию) простого ответа True / False. Фактический результат Python можно получить, установив для необязательного третьего аргумента значение None.
def xor(a, b, true=True, false=False): # set true to None to get actual Python result
ab1 = a and not b
ab2 = not a and b
if bool(ab1) != bool(ab2):
return (ab1 or ab2) if true is None else true
else:
return false
Как вы определяете «xor» для пары строк? Как вы думаете, что должно вернуть "abc" ^ "", а что нет?