如何在Python中得到两个变量的逻辑异或?

如何在Python中得到两个变量的逻辑异或? ide

例如,我有两个指望是字符串的变量。 我想测试其中只有一个包含True值(不是None或空字符串): 测试

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
if logical_xor(str1, str2):
    print "ok"
else:
    print "bad"

^运算符彷佛是按位的,而且未在全部对象上定义: lua

>>> 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楼

此处建议的某些实如今某些状况下会致使对操做数的重复评估,这可能致使意外的反作用,所以必须避免。 spa

也就是说,返回TrueFalsexor实现很是简单; 若是可能的话,返回一个操做数之一的技巧很是棘手,由于对于选择哪一个操做数没有共识,尤为是当有两个以上的操做数时。 例如, xor(None, -1, [], True)返回None[]False ? 我敢打赌,对于某些人来讲,每一个答案都是最直观的答案。 code

对于True或False结果,有多达五个可能的选择:返回第一个操做数(若是它与值中的最终结果匹配,不然为布尔值),返回第一个匹配项(若是至少存在一个,不然为布尔值),返回最后一个操做数(若是... else ...),返回最后一个匹配项(若是... else ...),或者始终返回布尔值。 总共有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()

#2楼

operator模块(与^运算符相同)已经内置在Python中的按位异或运算符: 字符串

from operator import xor
xor(bool(a), bool(b))  # Note: converting to bools is essential

#3楼

有时我发现本身使用1和0代替布尔True和False值。 在这种状况下,xor能够定义为 get

z = (x + y) % 2

它具备如下真值表: input

x
   |0|1|
  -+-+-+
  0|0|1|
y -+-+-+
  1|1|0|
  -+-+-+

#4楼

由于我看不到使用变量参数的xor的简单变体,而只对True值True或False进行运算,因此我将其扔给任何人使用。 正如其余人所指出的那样,它很是漂亮(不是很清楚)。 string

def xor(*vars):
    sum = 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的一种状况)。

所以,若是您要搜索仅在其中一个操做数正好存在时才为True的n元谓词,则可能须要使用:

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

#5楼

这将对两个(或多个)变量进行逻辑异或

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")

any([str1, str2]) and not all([str1, str2])

这种设置的第一个问题是,它极可能遍历整个列表两次,而且至少会两次检查至少一个元素。 所以,它可能会提升代码的理解能力,但并不能提升速度(根据您的使用状况而可能有所不一样)。

此设置的第二个问题是,不管变量数量如何,它都会检查排他性。 乍一看,这多是一个功能,可是随着变量数量的增长(若是有的话),第一个问题变得更加剧要。

相关文章
相关标签/搜索