การใช้งานบางอย่างที่แนะนำที่นี่จะทำให้การประเมินตัวถูกดำเนินการซ้ำ ๆ ในบางกรณีซึ่งอาจนำไปสู่ผลข้างเคียงที่ไม่ได้ตั้งใจดังนั้นจึงต้องหลีกเลี่ยง
ที่กล่าวว่าการxor
ดำเนินการที่ส่งกลับอย่างใดอย่างหนึ่งTrue
หรือFalse
ค่อนข้างง่าย; คนที่ส่งกลับหนึ่งในตัวถูกดำเนินการถ้าเป็นไปได้เป็นเรื่องยุ่งยากมากเพราะไม่มีความเห็นเป็นเอกฉันท์ว่าตัวถูกดำเนินการใดควรเลือกตัวเลือกใดโดยเฉพาะอย่างยิ่งเมื่อมีตัวถูกดำเนินการมากกว่าสองตัว ยกตัวอย่างเช่นควรxor(None, -1, [], True)
กลับNone
, []
หรือFalse
? ฉันเดิมพันว่าแต่ละคำตอบดูเหมือนกับบางคนว่าเป็นคำตอบที่ง่ายที่สุด
สำหรับ True- หรือ False-result มีตัวเลือกที่เป็นไปได้มากถึงห้าตัวเลือก: คืนค่าตัวถูกดำเนินการแรก (ถ้าตรงกับผลลัพธ์ที่สิ้นสุดในค่า, ค่าบูลอื่น), ส่งคืนการจับคู่ครั้งแรก (ถ้ามีอยู่อย่างน้อยหนึ่งรายการ ส่งคืนตัวถูกดำเนินการสุดท้าย (ถ้า ... อื่น ... ) ส่งคืนการจับคู่ล่าสุด (ถ้า ... อื่น ... ) หรือส่งคืนบูลีนเสมอ พรึบที่ 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()