Beberapa implementasi yang disarankan di sini akan menyebabkan evaluasi berulang operan dalam beberapa kasus, yang dapat menyebabkan efek samping yang tidak diinginkan dan karenanya harus dihindari.
Yang mengatakan, xor
implementasi yang mengembalikan salah satu True
atau False
cukup sederhana; yang mengembalikan salah satu operan, jika mungkin, jauh lebih rumit, karena tidak ada konsensus mengenai operan mana yang harus dipilih, terutama ketika ada lebih dari dua operan. Misalnya, harus xor(None, -1, [], True)
kembali None
, []
atauFalse
? Saya yakin setiap jawaban bagi sebagian orang tampak sebagai yang paling intuitif.
Untuk hasil Benar atau Salah, ada sebanyak lima pilihan yang mungkin: kembalikan operan pertama (jika cocok dengan hasil akhir dalam nilai, atau boolean), kembalikan kecocokan pertama (jika setidaknya ada satu, boolean lain), kembalikan operan terakhir (jika ... lain ...), kembalikan pertandingan terakhir (jika ... lain ...), atau selalu kembalikan boolean. Secara keseluruhan, itu 5 ** 2 = 25 rasa 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()