这里建议的一些实现在某些情况下会导致操作数重复评估,可能会导致意外的副作用,因此必须避免。
话虽如此,一个返回True
或False
的xor
实现相当简单;如果可能的话,返回其中一个操作数则要困难得多,因为没有共识可以选择哪个操作数,特别是当有两个以上的操作数时。例如,xor(None, -1, [], True)
应该返回None
、[]
还是False
?我敢打赌每个答案都会被一些人认为是最直观的。
对于真结果或假结果,有多达五种可能的选择:返回第一个操作数(如果它与最终结果匹配,则返回布尔值),返回第一个匹配项(如果至少存在一个,则返回布尔值),返回最后一个操作数(如果...否则...),返回最后一个匹配项(如果...否则...),或始终返回布尔值。总共有 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
for operand in operands:
value = bool(operand)
result ^= value
choice = choices[value]
if choice < -1 or (choice == -1 and value == result) or (choice == 1 and first) or (choice > 1 and value not in matches):
matches[value] = operand
first = False
if (choices[result] == -1) and (result != value):
return result
else:
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()
a xor a
被定义为(a and not b) or (not a and b)
,因此当a
和b
为字符串或任何其他类型时,a xor b
应该产生(a and not b) or (not a and b)
的结果。 - Kazint("0xFFFF00", 16) ^ int("0xFFFF00", 16) == int(0)
,所以你必须将其转换为数字并在结果上调用hex
,然后在左侧填充足够多的 0 以达到最长长度。 - Guimoute