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

当前回答

你使用和C中一样的异或运算符,也就是^。

我不知道为什么,但投票最多的解决方案是bool(A) != bool(B),而我想说的是-与C的^运算符一致,最明显的解决方案是:

bool(A) ^ bool(B)

对于任何来自C或任何C衍生语言的人来说,它更易于阅读和立即理解……

在进行代码高尔夫时,可能是这样

not A ^ (not B)

将是赢家。使用not作为布尔值的转换器(比bool()小一个字母)。对于第一个表达式在某些情况下可以省略副命题。好吧,这要看情况,在必须不(A) ^ (not(B))的情况下,bool()需要相同数量的字母……

其他回答

这是映射-缩减泛化的实现。注意,这相当于functools。Reduce (lambda x, y: x != y, map(bool, orands))。

def xor(*orands):
    return bool(sum(bool(x) for x in orands) % 2)

如果你在寻找一个单一热点探测器,这是一个概括。这种概括可能适用于英语中exclusive-or的用法(例如:“花一美元,你可以买一杯果汁、咖啡或茶”),但这与典型的操作顺序不符。E.g.xor_1hot (1 1 1) = = 0 ! = 1 = = xor_1hot (xor_1hot(1, 1), 1)。

def xor_1hot(*orands):
    return sum(bool(x) for x in orands) == 1

你可以用

# test
from itertools import product
n = 3
total_true = 0
for inputs in product((False, True), repeat=n):
    y = xor(*inputs)
    total_true += int(y)
    print(f"{''.join(str(int(b)) for b in inputs)}|{y}")
print('Total True:', total_true)

单热检测器输出:

000 |假 001 |真 010 |真 011 |假 100 |真 101 |假 110 |假 111 |假 总数正确:3

使用映射-规约模式输出:

000 |假 001 |真 010 |真 011 |假 100 |真 101 |假 110 |假 111 |真 总数:4

因为我没有看到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

你总是可以使用xor的定义从其他逻辑操作中计算它:

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

但这对我来说有点太啰嗦了,而且乍一看不是特别清楚。另一种方法是:

bool(a) ^ bool(b)

两个布尔值上的xor操作符是逻辑xor(不像整型值上的xor,它是按位的)。这是有意义的,因为bool只是int的一个子类,但被实现为只有值0和1。当域限制为0和1时,逻辑xor等价于按位xor。

所以logical_xor函数的实现方式如下:

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

感谢Python-3000邮件列表中的Nick Coghlan。

你使用和C中一样的异或运算符,也就是^。

我不知道为什么,但投票最多的解决方案是bool(A) != bool(B),而我想说的是-与C的^运算符一致,最明显的解决方案是:

bool(A) ^ bool(B)

对于任何来自C或任何C衍生语言的人来说,它更易于阅读和立即理解……

在进行代码高尔夫时,可能是这样

not A ^ (not B)

将是赢家。使用not作为布尔值的转换器(比bool()小一个字母)。对于第一个表达式在某些情况下可以省略副命题。好吧,这要看情况,在必须不(A) ^ (not(B))的情况下,bool()需要相同数量的字母……

Python逻辑或:A或B:如果bool(A)为True则返回A,否则返回B Python逻辑和:A和B:如果bool(A)为False则返回A,否则返回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'