如何在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'

当前回答

Python有一个逐位的异或运算符,它是^:

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

你可以在应用xor(^)之前将输入转换为布尔值来使用它:

bool(a) ^ bool(b)

(编辑-谢谢雷尔)

其他回答

Exclusive Or的定义如下

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

只是因为我没有在其他地方看到过它,这也是一个诀窍:

def logical_xor(a, b):
    return not b if a else bool(b)

我不确定它是否比公认的解决方案bool(a) != bool(b)“更好”/更可读/更python化。

我已经测试了几种方法(包括使用shadow wranger建议的truth()函数)。

%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

在Python中获取两个或多个变量的逻辑异或:

将输入转换为布尔值 使用按位的异或操作符(^ or operator.xor)

例如,

bool(a) ^ bool(b)

当您将输入转换为布尔值时,按位xor变成逻辑xor。

请注意,接受的答案是错误的:!=与Python中的xor不同,因为操作符链接非常微妙。

例如,下面三个值的xor在使用!=时是错误的:

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

(附注:我尝试编辑已接受的答案,以包含这一警告,但我的更改被拒绝了。)

因为我没有看到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元逻辑异或,当True操作数的数量为奇数时,它的真值将为True(不仅仅是当恰好有一个为True时,这只是n元异或为True的一种情况)。

因此,如果你在搜索一个n-ary谓词,当它的一个操作数恰好为True时,它才为True,你可能想使用:

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