How do you get the logical xor of two variables in Python?
如何获得Python中两个变量的逻辑XOR?
例如,我有两个期望是字符串的变量。我想测试它们中只有一个包含真值(不是无或空字符串):
1 2 3 4 5 6 | str1 = raw_input("Enter string one:") str2 = raw_input("Enter string two:") if logical_xor(str1, str2): print"ok" else: print"bad" |
1 2 3 4 5 6 7 8 | >>> 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' |
如果您已经在规范布尔值的输入,那么!=异或。
1 | bool(a) != bool(b) |
您始终可以使用xor的定义从其他逻辑操作计算它:
1 | (a and not b) or (not a and b) |
但这对我来说有点过于冗长,乍一看也不太清楚。另一种方法是:
1 | bool(a) ^ bool(b) |
两个布尔值上的xor运算符是逻辑xor(与int不同,它是按位的)。这是有道理的,因为
因此,
1 2 | def logical_xor(str1, str2): return bool(str1) ^ bool(str2) |
归功于python-3000邮件列表中的nick coghlan。
在
1 2 | from operator import xor xor(bool(a), bool(b)) |
正如扎克所解释的,你可以使用:
1 | xor = bool(a) ^ bool(b) |
就我个人而言,我喜欢一种稍微不同的方言:
1 | xor = bool(a) + bool(b) == 1 |
这种方言是从我在学校学过的一种逻辑图表语言中得到启发的,其中"or"由一个包含
这具有正确实现异或多个操作数的优点。
- "1=a^b^c…"表示真正的操作数是奇数。这个运算符是"奇偶校验"。
- "1=a+b+c…"表示只有一个操作数为真。这是"排他性的或",意思是"一方排除另一方"。
- python逻辑
or :A or B :如果bool(A) 是True 则返回A ,否则返回B 。 - python逻辑
and :A and B :如果bool(A) 是False 则返回A ,否则返回B 。
为了保持这种思维方式,我的逻辑XOR定义是:
1 2 3 4 5 | def logical_xor(a, b): if bool(a) == bool(b): return False else: return a or b |
这样可以返回
1 2 3 4 5 6 7 8 | >>> logical_xor('this', 'that') False >>> logical_xor('', '') False >>> logical_xor('this', '') 'this' >>> logical_xor('', 'that') 'that' |
我已经测试了几种方法,其中
这是一些测试
1 2 3 4 5 6 7 8 | %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 |
我知道这很晚了,但我有一个想法,这可能是值得的,只是为了记录。也许这会奏效:
奖励线:
更重要的想法…只是你试试(可能是)Python的表情?不是吗?为了得到合乎逻辑的行为?异或?
真相表应该是:
1 2 3 4 5 6 7 8 9 | >>> True is not True False >>> True is not False True >>> False is not True True >>> False is not False False >>> |
对于您的示例字符串:
1 2 3 4 5 6 7 8 9 10 11 | >>>"abc" is not "" True >>> 'abc' is not 'abc' False >>> 'abc' is not '' True >>> '' is not 'abc' True >>> '' is not '' False >>> |
然而,正如上面所指出的,这取决于您想要对任何一对字符串进行提取的实际行为,因为字符串不是Boleans…更重要的是:如果你?潜入Python?你会发现吗?"和"和"或"的特殊性质?http://www.diveintopython.net/power_of_introspection/and_or.html
对不起,我写的英语,不是我天生的语言。
当做。
因为我没有看到XOR的简单变体使用变量参数,并且只对真值true或false进行操作,所以我将把它扔到这里供任何人使用。正如其他人所指出的,相当(不是说非常)直截了当。
1 2 3 4 5 | def xor(*vars): sum = bool(False) for v in vars: sum = sum ^ bool(v) return sum |
使用也很简单:
1 2 | if xor(False, False, True, False): print"Hello World!" |
因为这是广义的n元逻辑异或,所以当真操作数的数目为奇数时,它的真值将为真(不仅当一个真操作数为真时,这只是n元异或为真的一种情况)。
因此,如果您正在搜索一个n元谓词,而该谓词只有在其中一个操作数为时才为真,则可能需要使用:
1 2 3 4 5 6 7 8 | def isOne(*vars): sum = bool(False) for v in vars: if sum and v: return False else: sum = sum or v return sum |
排他或定义如下
1 2 | def xor( a, b ): return (a or b) and not (a and b) |
简单易懂:
1 | sum( (bool(a), bool(b) ) == 1 |
如果您所追求的是独占选择,则可以将其扩展为多个参数:
1 | sum( bool(x) for x in y ) == 1 |
有时我发现自己使用的是1和0,而不是布尔的真值和假值。在这种情况下,xor可以定义为
1 | z = (x + y) % 2 |
它有以下真值表:
1 2 3 4 5 6 7 | x |0|1| -+-+-+ 0|0|1| y -+-+-+ 1|1|0| -+-+-+ |
这个怎么样?
1 | (not b and a) or (not a and b) |
如果
或者使用python 2.5+三元表达式:
1 | (False if a else b) if b else a |
这里建议的一些实现在某些情况下会导致对操作数的重复评估,这可能导致意外的副作用,因此必须避免。
也就是说,返回
对于"真"或"假"结果,可能有五种选择:返回第一个操作数(如果它与值中的最终结果匹配,则为布尔值)、返回第一个匹配项(如果至少存在一个操作数,则为布尔值)、返回最后一个操作数(如果…否则…),返回最后一个匹配项(如果…否则…)或始终返回布尔值。总共是5*2=25种
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | 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在
当你知道XOR的作用时很容易:
1 2 3 4 5 6 7 8 9 10 11 12 | 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)) |
这将获取两个(或更多)变量的逻辑异或
1 2 3 4 | str1 = raw_input("Enter string one:") str2 = raw_input("Enter string two:") any([str1, str2]) and not all([str1, str2]) |
这个设置的第一个问题是,它很可能会遍历整个列表两次,并且至少会检查其中一个元素两次。因此,它可能会提高代码的理解能力,但它不适用于速度(根据您的用例,速度可能存在明显的差异)。
这个设置的第二个问题是,不管变量的数量如何,它都会检查排他性。这一点一开始可能被视为一个特性,但随着变量数量的增加(如果有),第一个问题变得更加重要。
许多人,包括我自己,都需要一个
1 2 3 4 5 6 7 | 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) |
示例I/O如下:
1 2 3 4 5 6 7 8 | 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 |
xor是python中的
- 整数的位异或
- 布尔值的逻辑异或
- 集合的独占联合
- 实现
__xor__ 的类的用户定义结果。 - 未定义类型(如字符串或字典)的类型错误。
如果你想在字符串上使用它们,把它们放在
我们可以通过以下方法很容易地找到两个变量的xor:
1 2 | def xor(a,b): return a !=b |
例子:
xor(True,False) >>> True
< /块引用>< /块引用>