Как вы получаете логический xor двух переменных в Python? - PullRequest
544 голосов
/ 11 января 2009

Как вы получаете логический 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'

Ответы [ 21 ]

1032 голосов
/ 11 января 2009

Если вы уже нормализуете входные значения для логических значений, тогда! = Is xor.

bool(a) != bool(b)
421 голосов
/ 11 января 2009

Вы всегда можете использовать определение xor для вычисления его из других логических операций:

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

Но для меня это слишком многословно и на первый взгляд не совсем понятно. Еще один способ сделать это:

bool(a) ^ bool(b)

Оператор xor на двух логических значениях является логическим xor (в отличие от целых, где он побитовый). Что имеет смысл, поскольку bool является просто подклассом int, но реализован так, чтобы иметь значения 0 и 1 И логический xor эквивалентен битовому xor, когда домен ограничен 0 и 1.

Таким образом, функция logical_xor будет реализована следующим образом:

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

Кредит Нику Коглану в списке рассылки Python-3000 .

161 голосов
/ 14 июня 2012

Эксклюзивно или уже встроено в Python, в модуле operator:

from operator import xor
xor(bool(a), bool(b))
35 голосов
/ 11 января 2009

Как объяснил Зак , вы можете использовать:

xor = bool(a) ^ bool(b)

Лично я предпочитаю немного другой диалект:

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

Этот диалект навеян языком логических диаграмм, который я выучил в школе, где «ИЛИ» обозначалось полем, содержащим ≥1 (больше или равно 1), а «XOR» обозначалось полем, содержащим =1 .

Преимущество заключается в правильной реализации монопольного или нескольких операндов.

  • «1 = a ^ b ^ c ...» означает, что число истинных операндов нечетно. Этот оператор является «четность».
  • «1 = a + b + c ...» означает, что истинно только один операнд. Это «исключительный или», что означает «один за исключением других».
23 голосов
/ 11 января 2009
  • Python логический or: A or B: возвращает A, если bool(A) равен True, в противном случае возвращается B
  • Python логический and: 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'
17 голосов
/ 04 февраля 2016

Я протестировал несколько подходов, и not a != (not b) оказался самым быстрым.

Вот несколько тестов

%timeit not a != (not b)
10000000 loops, best of 3: 78.5 ns per loop

In [130]: %timeit bool(a) != bool(b)
1000000 loops, best of 3: 343 ns per loop

In [131]: %timeit not a ^ (not b)
10000000 loops, best of 3: 131 ns per loop
8 голосов
/ 20 мая 2016

Награждение темы:

Идея анодера ... Просто попробуйте (может быть) питоническое выражение «нет», чтобы получить логическое поведение «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

Извините, что я написал на английском, это не мой родной язык.

Привет.

7 голосов
/ 02 августа 2016

Я знаю, что уже поздно, но у меня была мысль, и она могла бы стоить, просто для документации. Возможно, это сработает: np.abs(x-y) Идея в том, что

  1. если x = True = 1 и y = False = 0, то результатом будет | 1-0 | = 1 = True
  2. если x = False = 0 и y = False = 0, то результатом будет | 0-0 | = 0 = False
  3. если x = True = 1 и y = True = 1, то результатом будет | 1-1 | = 0 = False
  4. если x = False = 0 и y = True = 1, то результатом будет | 0-1 | = 1 = True
7 голосов
/ 20 апреля 2010

Поскольку я не вижу простого варианта xor, использующего переменные аргументы и только операции со значениями True, True или False, я просто брошу его здесь для любого использования. Это, как отмечают другие, довольно (если не сказать очень) просто.

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

И использование также просто:

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

Поскольку это обобщенный n-арный логический XOR, его значение истины будет True, когда число операндов True нечетно (и не только, когда ровно один равен True, это только один случай, когда n-арный XOR True).

Таким образом, если вы ищете n-арный предикат, который имеет значение True только тогда, когда точно один из его операндов, вы можете использовать:

def isOne(*vars):
    sum = bool(False)
    for v in vars:
        if sum and v:
            return False
        else:
            sum = sum or v
    return sum
7 голосов
/ 11 января 2009

исключая или определяется следующим образом

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