여기에 제안 된 구현 중 일부는 피연산자를 반복적으로 평가하여 의도하지 않은 부작용으로 이어질 수 있으므로 피해야합니다.
그건 말했다 xor
반환하거나 것을 구현 True
하거나 False
매우 간단하다; 피연산자 중 하나를 반환하는 피연산자는 가능한 경우 훨씬 까다 롭습니다. 특히 피연산자가 둘 이상인 경우 어떤 피연산자를 선택해야하는지에 대한 합의가 없기 때문입니다. 예를 들어,해야 xor(None, -1, [], True)
반환 None
, []
또는 False
? 각 답변은 일부 사람들에게 가장 직관적 인 답변으로 보입니다.
True- 또는 False-result의 경우 가능한 5 가지 선택 사항이 있습니다. 첫 번째 피연산자 리턴 (값이 최종 결과와 일치하는 경우 부울 임), 첫 번째 일치 리턴 (최소 하나가 존재하는 경우 부울) 마지막 피연산자 반환 (if ... else ...), 마지막 일치 반환 (if ... 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()