如何在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])

這種設置的第一個問題是,它極可能遍歷整個列表兩次,而且至少會兩次檢查至少一個元素。 所以,它可能會提升代碼的理解能力,但並不能提升速度(根據您的使用狀況而可能有所不一樣)。

此設置的第二個問題是,不管變量數量如何,它都會檢查排他性。 乍一看,這多是一個功能,可是隨着變量數量的增長(若是有的話),第一個問題變得更加劇要。

相關文章
相關標籤/搜索