คุณจะรับตรรกะ xor ของสองตัวแปรใน Python ได้อย่างไร


648

คุณจะรับตรรกะ xorของตัวแปรสองตัวใน Python ได้อย่างไร

ตัวอย่างเช่นฉันมีสองตัวแปรที่ฉันคาดว่าจะเป็นสตริง ฉันต้องการทดสอบว่ามีเพียงหนึ่งในนั้นที่มีค่า True (ไม่ใช่ None หรือสตริงว่าง):

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")
if logical_xor(str1, str2):
    print "ok"
else:
    print "bad"

^ประกอบการน่าจะเป็นค่าที่เหมาะสมและไม่ได้กำหนดไว้ในวัตถุทั้งหมด:

>>> 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'

3
คุณจะกำหนด "xor" สำหรับสองสายได้อย่างไร? คุณรู้สึกอย่างไร "abc" ^ "" ควรกลับมาที่มันไม่?
Mehrdad Afshari

18
มันควรจะคืนค่าจริงแทนที่จะยกข้อยกเว้นเนื่องจากมีเพียงหนึ่งในสตริงที่เป็นจริงตามที่กำหนดโดยประเภทบูลของงูใหญ่
Zach Hirsch

38
ฉันประหลาดใจที่ Python ไม่มีโอเปอเรเตอร์ infix ที่เรียกว่า "xor" ซึ่งจะเป็นการใช้งาน Pythonic ที่ใช้งานง่ายที่สุด การใช้ "^" นั้นสอดคล้องกับภาษาอื่น แต่ไม่สามารถอ่านได้อย่างโจ่งแจ้งเหมือนกับ Python ส่วนใหญ่
Mark E. Haase

13
@ MehrdadAfshari คำตอบที่ชัดเจนสำหรับคำถามของคุณa xor aคือคำจำกัดความว่า(a and not b) or (not a and b)ดังนั้นa xor bเมื่อใดaและbเป็นสตริงอักขระหรือประเภทอื่น ๆ ควรให้ผลตอบแทนใด(a and not b) or (not a and b)
Kaz

1
ปัญหาคือเอกสารไม่ดี ^ คือ "bitwise exclusive หรือ" ซึ่งแปลตามตัวอักษรหมายถึงแบบทีละบิตไม่ใช่บูลโดยบูล ดังนั้น x'FFFF00 '^ x'FFFF00' ควรเป็น x'000000 ' หรือนี่จะหมายถึงเฉพาะที่จะเกิดขึ้นบนถ่านโดยพื้นฐานถ่าน? โยนเป็นตัวเลขหรือไม่ เราจำเป็นต้องย้ำอักขระสตริงที่สั้นกว่าเพื่อให้ตรงกับความยาวของสตริงที่ยาวกว่า ทั้งหมดนี้ควรสร้างขึ้นมา
mckenzm

คำตอบ:


1187

หากคุณกำลังปรับอินพุตอินพุตเป็นบูลีนเป็นปกติอยู่แล้ว! = คือ xor

bool(a) != bool(b)

148
แม้ว่านี่จะฉลาดและสั้น แต่ฉันก็ไม่เชื่อว่ามันจะสะอาด เมื่อมีคนอ่านโครงสร้างนี้ในรหัสมันชัดเจนทันทีว่านี่เป็นการดำเนินการของ xor หรือไม่? ฉันรู้สึกว่าจำเป็นต้องเพิ่มความคิดเห็น - สัญญาณสำหรับฉันที่ฉันเขียนรหัสไม่ชัดเจนและพยายามขอโทษด้วยความคิดเห็น

47
บางที "เห็นได้ชัดว่าเป็นแฮคเกอร์หรือไม่" เป็นคำถามที่ผิด เราแค่พยายามดูว่าคำตอบของสองคำถามเหมือนกันหรือไม่และคิดว่าเราจะใช้แฮคเกอร์เพื่อดำเนินการนั้น ตัวอย่างเช่นหากเราต้องการให้แน่ใจว่าเราไม่ได้เปรียบเทียบแอปเปิ้ลกับส้มคือ "if xor (isApple (x), isApple (y))" ชัดเจนกว่าจริง ๆ "if isApple (x)! = isApple (y)"? ไม่ใช่สำหรับฉัน!
AmigoNico

106
มีปัญหากับการใช้ "! =" เป็น xor คุณอาจคาดหวัง bool (a)! = bool (b)! = bool (c) ให้เหมือนกับ bool (a) ^ bool (b) ^ bool (c) ดังนั้นมันได้ปลดเปลื้องกับบูล แต่ฉันอยากจะแนะนำ ^ หากต้องการทราบว่าเกิดอะไรขึ้นในตัวอย่างแรกให้ค้นหา "การโยงผู้ปฏิบัติงาน"
elmo

19
@elmo: +1 สำหรับการชี้ให้เห็นความแตกต่างและ +1 สำหรับการสอนให้ฉันทราบว่าการผูกมัดผู้ประกอบการคืออะไร! ฉันอยู่ในค่ายที่บอกว่า! = ไม่สามารถอ่านได้เหมือน ^
Mark E. Haase

13
มันควรจะเป็นbool(a) is not bool(b)แทน
RNA

485

คุณสามารถใช้คำจำกัดความของ xor เพื่อคำนวณจากการดำเนินการเชิงตรรกะอื่น ๆ :

(a and not b) or (not a and b)

แต่นี่เป็น verbose เล็กน้อยเกินไปสำหรับฉันและไม่ชัดเจนโดยเฉพาะอย่างยิ่งได้อย่างรวดเร็วก่อน อีกวิธีที่จะทำคือ:

bool(a) ^ bool(b)

ตัวดำเนินการ xor ใน booleans สองตัวคือ xor แบบลอจิคัล (ซึ่งแตกต่างจาก ints ซึ่งเป็นค่าบิต) ซึ่งจะทำให้รู้สึกตั้งแต่boolเป็นเพียง subclass ของintแต่จะดำเนินการจะมีเพียงค่าและ0 1และ xor ตรรกะเทียบเท่ากับค่าที่เหมาะสม xor เมื่อโดเมนจะมีการ จำกัดและ01

ดังนั้นlogical_xorฟังก์ชั่นจะถูกนำไปใช้เช่น:

def logical_xor(str1, str2):
    return bool(str1) ^ bool(str2)

เครดิตให้กับนิค Coghlan ในหลาม-3000 รายชื่อผู้รับจดหมาย


7
โพสต์ที่ยอดเยี่ยม แต่วิธีตั้งชื่อพารามิเตอร์ของคุณทำไมจึงเป็น 'str1' และ 'str2'
SingleNegationElimination

1
@ พูดทำไมไม่ คุณหมายถึงเพราะพวกเขาไม่ได้เป็น Pythonic มาก?
orokusaki

1
@ Zach Hirsch คุณสามารถใช้ (ไม่ใช่ a และ b) แทน (b และไม่ใช่ a) เพื่อให้สามารถอ่านได้หรือคำจำกัดความไม่สอดคล้องกับ xor
orokusaki

10
คุณควรใส่ nots ก่อนเช่นนี้(not b and a) or (not a and b)เพื่อให้ส่งคืนสตริงหากมีหนึ่งซึ่งดูเหมือนว่าเป็นวิธี pythonic สำหรับฟังก์ชั่นการใช้งาน
rjmunro

2
@TokenMacGuy: คุณแนะนำอะไรให้เขาตั้งชื่อพวกเขาแทน?
541686

180

Bitwiseแบบเอกสิทธิ์เฉพาะบุคคลหรือมีอยู่แล้วใน Python ในoperatorโมดูล (ซึ่งเหมือนกับตัว^ดำเนินการ):

from operator import xor
xor(bool(a), bool(b))  # Note: converting to bools is essential

3
นี่คือสิ่งที่ฉันต้องการ เมื่อย้อนกลับมัลแวร์วิศวกรรมย้อนกลับหลายครั้งสตริงจะถูกจัดการจนกระทั่งการดำเนินการ XOR ใช้ chr นี้ (xor (ord ("n"), 0x1A)) = 't'
ril3y

75
ระวังนี้ยังเป็นค่าที่เหมาะสม: ผลตอบแทนxor(1, 2) 3จาก docstring: xor(a, b) -- Same as a ^ b. โปรดจำไว้ว่าสิ่งที่นำเข้าจากoperatorนั้นเป็นเพียงรูปแบบการทำงานของตัวดำเนินการ infin ที่มีอยู่แล้ว
askewchan

5
@askewchan: boolประเภทโอเวอร์โหลด__xor__เพื่อส่งคืนบูลีน มันจะทำงานได้ดี แต่ overkill ของมันเมื่อbool(a) ^ bool(b)ทำสิ่งเดียวกัน
Martijn Pieters

@MartijnPieters ^ผู้ให้บริการโทรศัพท์__xor__ภายใน
Quantum7

5
@ Quantum7: ใช่ฉันไม่แน่ใจว่าทำไมคุณถึงบอกเรื่องนี้กับฉัน ผมแค่บอกว่าboolประเภทดำเนินการ__xor__วิธีการเฉพาะเพราะ^เรียกมันว่า จุดที่ใช้bool(a) ^ bool(b)งานได้ดีไม่จำเป็นต้องใช้operator.xor()ฟังก์ชั่นที่นี่
Martijn Pieters

43

ตามที่Zachอธิบายไว้คุณสามารถใช้:

xor = bool(a) ^ bool(b)

โดยส่วนตัวแล้วฉันชอบภาษาที่แตกต่างกันเล็กน้อย:

xor = bool(a) + bool(b) == 1

ภาษานี้ได้รับแรงบันดาลใจจากภาษาไดอะแกรมเชิงตรรกะที่ฉันได้เรียนในโรงเรียนที่มี "OR" กำกับโดยกล่องที่มี≥1(มากกว่าหรือเท่ากับ 1) และ "XOR" ถูกเขียนแทนด้วยกล่องที่มี=1ถูกแทนด้วยกล่องใส่

นี่เป็นข้อได้เปรียบของการใช้งานแบบเอกสิทธิ์เฉพาะบุคคลหรือตัวถูกดำเนินการหลายตัวอย่างถูกต้อง

  • "1 = a ^ b ^ c ... " หมายถึงจำนวนตัวถูกดำเนินการจริงเป็นเลขคี่ ผู้ประกอบการนี้คือ "ความเท่าเทียมกัน"
  • "1 = a + b + c ... " หมายถึงหนึ่งตัวถูกดำเนินการจริง นี่คือ "พิเศษหรือ" ความหมาย "หนึ่งเพื่อการยกเว้นของคนอื่น"

12
ดังนั้นจริง + จริง + เท็จ + จริง == 3 และ 3! = 1 แต่จริง XOR จริง XOR จริง XOR เท็จ XOR จริง == จริง คุณสามารถอธิบายรายละเอียดเกี่ยวกับ "การใช้ XOR อย่างถูกต้องกับตัวถูกดำเนินการหลายตัว" ได้หรือไม่?
tzot

3
@tzot ตัวอย่างของคุณล้มเหลวเนื่องจากวิธีการแก้ปัญหาของ ddaa คุณสามารถเพิ่มตัวแปรได้ครั้งละสองตัวเท่านั้น (((((True + True)==1)+False)==1)+True)==1ดังนั้นวิธีการที่เหมาะสมที่จะเขียนมันออกทั้งหมดจะต้องมีการ คำตอบที่ให้ที่นี่พูดคุยกับตัวถูกดำเนินการหลายตัวโดยสิ้นเชิง
ely

6
นอกจากนี้ยังมีความแตกต่างระหว่างชุด XOR สามทางกับชุดลำดับการปฏิบัติการที่จัดกลุ่มเป็นสองชุด ดังนั้น 3-WAY-XOR (A, B, C) ไม่เหมือนกับ XOR (XOR (A, B), C) และตัวอย่างของ dda คืออดีตในขณะที่คุณสมมติหลัง
ely

3
@ Mr.F คำอธิบายของคุณไม่ได้แก้ตัวจริง ๆ คำตอบนี้ ในหลามถ้าคุณทำTrue + True + False + Trueคุณจะได้รับ3และTrue + True + False + True == 3ให้กลับไปTrueในขณะที่ให้กลับTrue + True + False + True == 1 Falseกล่าวอีกนัยหนึ่งคำตอบที่นี่ไม่ได้พูดคุยอย่างถูกต้อง เพื่อให้ทำเช่นนั้นคุณจะต้องทำงานเพิ่มเติม ในขณะเดียวกันก็True ^ True ^ False ^ Trueทำงานง่าย ๆ อย่างที่คาดไว้
jpmc26

3
@ jpmc26 ฉันไม่เข้าใจความคิดเห็นของคุณ วิธีการเพิ่มเติมนั้นหมายถึงการดำเนินการทั่วไปที่คุณต้องการตรวจสอบว่าหนึ่งตัวถูกดำเนินการคือTruemulti-arity XOR A XOR B XOR ... XOR Zนี้คือการดำเนินการที่แตกต่างกันกว่ายกตัวอย่างเช่น ในคำอื่น ๆ ถ้าคุณวางแผนที่จะใช้รุ่นนอกจากนี้ตามแล้วเมื่อส่งตัวถูกดำเนินการในTrue + True + False + Trueคุณควรคาดหวังผลที่จะเป็นFalseตั้งแต่มากกว่าหนึ่งในนั้นคือที่ทำงานถ้าการตรวจสอบเงื่อนไขในการTrue == 1
ely

26
  • งูหลามตรรกะor: A or B: กลับAถ้าbool(A)มีTrueมิฉะนั้นส่งคืนB
  • Python แบบโลจิคัลand:: A and Bส่งคืนAif bool(A)is Falseมิฉะนั้นส่งคืนB

เพื่อให้ส่วนใหญ่ของวิธีการคิด, ตรรกะ XOR เชิงตรรกะของฉันจะเป็น:

def logical_xor(a, b):
    if bool(a) == bool(b):
        return False
    else:
        return a or b

วิธีการที่จะสามารถกลับa, bหรือFalse:

>>> logical_xor('this', 'that')
False
>>> logical_xor('', '')
False
>>> logical_xor('this', '')
'this'
>>> logical_xor('', 'that')
'that'

5
ดูเหมือนว่าจะไม่ดีหรืออย่างน้อยก็แปลกสำหรับฉัน ไม่มีตัวดำเนินการเชิงตรรกะตัวอื่น ๆ ที่ส่งคืนค่าที่เป็นไปได้หนึ่งในสามค่า
Zach Hirsch

2
@Zach เฮิร์ช: นั่นเป็นเหตุผลที่ผมกล่าวว่า "เพื่อให้มากที่สุดของวิธีคิดที่" - เนื่องจากไม่มีผลงานที่ดีเมื่อทั้งสองเป็นจริงหรือเท็จ
nosklo

การดำเนินการเชิงตรรกะต้องส่งคืนค่าโลจิคัลดังนั้นวินาที "return a หรือ b" ดูแปลกดังนั้นการส่งคืนที่สองต้องส่งคืน True
เดนิส Barmenkov

9
@Denis Barmenkov: โปรดทราบว่าตัวดำเนินการทางตรรกะของหลามandและorจะไม่ส่งคืนค่าตรรกะ 'foo' and 'bar'ส่งคืน'bar'...
nosklo

6
ที่เห็นครั้งแรกที่ 2 คำตอบก่อนหน้านี้ดูเหมือนที่ดีที่สุด แต่ในความคิดที่สองคนนี้เป็นจริงเท่านั้นที่ถูกต้องอย่างแท้จริงหนึ่งคือมันเป็นเพียงคนเดียวที่ให้ตัวอย่างของหนึ่งxorการดำเนินงานที่สอดคล้องกับในตัวและand orอย่างไรก็ตามแน่นอนว่าในสถานการณ์จริงbool(a) ^ bool(b)หรือแม้กระทั่งa ^ b(ถ้าaและbเป็นที่รู้กันว่าbool) มีความรัดกุมมากกว่า
Erik Kaplun

23

ฉันทดสอบหลายวิธีแล้วและnot a != (not b)ดูเหมือนจะเร็วที่สุด

นี่คือการทดสอบบางอย่าง

%timeit not a != (not b)
10000000 loops, best of 3: 78.5 ns per loop

%timeit bool(a) != bool(b)
1000000 loops, best of 3: 343 ns per loop

%timeit not a ^ (not b)
10000000 loops, best of 3: 131 ns per loop

แก้ไข: ตัวอย่างที่ 1 และ 3 ด้านบนขาดวงเล็บดังนั้นผลลัพธ์ไม่ถูกต้อง ใหม่ผลลัพธ์ + truth()ฟังก์ชั่นตามที่แนะนำ ShadowRanger

%timeit  (not a) ^  (not b)   # 47 ns
%timeit  (not a) != (not b)   # 44.7 ns
%timeit truth(a) != truth(b)  # 116 ns
%timeit  bool(a) != bool(b)   # 190 ns

6
นั่นคือ 100 ns ในชีวิตของฉันฉันจะไม่ได้รับกลับมา ;-)
Arel

4
สำหรับในระหว่างระยะเวลาที่คุณสามารถทำที่ด้านบนของโมดูลและการทดสอบfrom operator import truth เป็นตัวสร้างได้จำนวนมากของค่าใช้จ่ายที่หลีกเลี่ยงไม่ได้ในระดับ C (มันต้องยอมรับข้อโต้แย้งเป็นเทียบเท่าและแยกและเพื่อดึงพวกเขา) ที่(เป็นฟังก์ชั่น) สามารถใช้เป็นเส้นทางที่ดีที่สุดที่ไม่ต้องใช้อย่างใดอย่างหนึ่งหรือ a และทำงานในเวลาประมาณครึ่งหนึ่งของโซลูชันพื้นฐาน (แต่ยังยาวกว่าโซลูชันพื้นฐาน) truth(a) != truth(b)bool*args, **kwargstupledicttruthtupledictboolnot
ShadowRanger

9

ด้ายรางวัล:

แนวคิด Anoder ... เพียงคุณลองใช้การแสดงออกแบบ pythonic (ไม่ใช่) เพื่อรับพฤติกรรมของตรรกะ« xor »

ตารางความจริงจะเป็น:

>>> True is not True
False
>>> True is not False
True
>>> False is not True
True
>>> False is not False
False
>>>

และสำหรับสตริงตัวอย่างของคุณ:

>>> "abc" is not  ""
True
>>> 'abc' is not 'abc' 
False
>>> 'abc' is not '' 
True
>>> '' is not 'abc' 
True
>>> '' is not '' 
False
>>> 

อย่างไรก็ตาม; ตามที่ระบุไว้ข้างต้นมันขึ้นอยู่กับพฤติกรรมที่แท้จริงที่คุณต้องการดึงออกมาเกี่ยวกับสตริงคู่เพราะสตริงไม่ได้เป็น boleans ... และอีกมากมาย: ถ้าคุณ« Dive Into Python »คุณจะพบ« The Peculiar Nature of " และ "และ" หรือ "» http://www.diveintopython.net/power_of_introspection/and_or.html

ขออภัยที่เขียนเป็นภาษาอังกฤษไม่ใช่ภาษาที่ฉันเกิด

ความนับถือ.


ฉันยังใช้ในการอ่านว่า "แตกต่างอย่างเคร่งครัด" นั่นเป็นเพราะบางภาษาใช้เพื่อดำเนินการบิตการดำเนินการของการเป็นตัวแทนไบนารีและใช้บูลของการดำเนินการระดับบิตที่เกิดขึ้น ฉันเดาคำตอบของคุณคือ "กระสุนชนิดกันกระสุน" มากกว่าเพราะมันขยายเกินพื้นที่บูลีน
yucer

ฉันหมายถึงความจริงที่ว่าคำตอบของคุณครอบคลุมกรณีของการเปรียบเทียบไม่มี, เท็จ, '' แตกต่างกันคือสิ่งที่แตกต่าง ตัวอย่างเช่น: bool (เท็จ)! = bool ('') อย่างไรก็ตาม False ไม่ใช่ '' "เห็นด้วยมากขึ้นกับความหมายของ" แตกต่างอย่างเคร่งครัด "นี้
yucer

8

Python มีตัวดำเนินการพิเศษ OR ระดับบิตมันคือ^:

>>> True ^ False
True
>>> True ^ True
False
>>> False ^ True
True
>>> False ^ False
False

คุณสามารถใช้มันได้โดยแปลงอินพุตเป็นบูลีนก่อนที่จะใช้ xor ( ^):

bool(a) ^ bool(b)

(แก้ไข - ขอบคุณ Arel)


คำตอบของคุณควรตรวจสอบให้ชัดเจนว่า^เป็นค่าที่เหมาะสม xor (ไม่ xor ตรรกะเช่นคำถามที่ถาม) ช่วยให้คำตอบที่แตกต่างกว่าbool(2) ^ bool(3) bool(2 ^ 3)
Arel

1
@Arel แต่นั่นไม่ใช่กรณี a ^ bคือ polymorph หากaและbเป็นboolกรณีผลลัพธ์ก็จะเป็นboolเช่นกัน พฤติกรรมนี้แทบจะเรียกได้ว่าเป็น "bitwise" xor
Alfe

@ ทราบว่าจุดสำคัญคือค่าจะต้องถูกส่งไปยังบูลีนก่อน เอกสาร Python กำหนด^เป็นค่าบิตแม้ว่ามันจะเป็นจุดที่น่าสนใจที่ประเภทจะถูกเก็บรักษาไว้boolและintประเภท หมายเหตุ: True ^ 2คือ3แสดงให้เห็นถึงวิธีการที่เหมาะสมจริง ๆ
Arel

@Arel ใช่bool ^ intกรณีของการหล่อทุกอย่างintก่อน ยังคงหลามได้ในตัว^ผู้ประกอบการสำหรับบิตจำนวนมากในintและเป็นหนึ่งบิตเป็นตัวแทนในboolเพื่อให้ทั้งสองมีค่าที่เหมาะสมแต่บิต xor สำหรับบิตเดียวเพียงเป็นตรรกะ xor สำหรับ booleans
Alfe

ฉันมักจะเกลียดการใช้โอเปอเรเตอร์นี้ถึงแม้ว่าฉันจะเข้าใจว่ามันxorมาจากภูมิหลังทางวิศวกรรมสำหรับฉันแล้วสัญชาตญาณนี้ให้ความรู้สึกเหมือนพลังคณิตศาสตร์นั่นคือ2^3 = pow(2,3)หมายความว่าฉันมักจะแสดงความคิดเห็นอย่างชัดเจนเพื่อป้องกันความสับสน
นิโคลัสแฮมิลตัน

8

ในขณะที่ฉันไม่เห็นตัวแปรง่าย ๆ ของ xor โดยใช้อาร์กิวเมนต์อาร์กิวเมนต์และการดำเนินการกับค่าความจริงเป็นเท็จเท่านั้นฉันจะทิ้งมันไว้ที่นี่เพื่อให้ทุกคนใช้ มันเป็นที่สังเกตโดยคนอื่น ๆ สวย (ไม่พูดมาก) ตรงไปตรงมา

def xor(*vars):
    sum = False
    for v in vars:
        sum = sum ^ bool(v)
    return sum

และการใช้งานก็เรียบง่ายเช่นกัน:

if xor(False, False, True, False):
    print "Hello World!"

เนื่องจากนี่คือตรรกะ XOR แบบ N-ary ทั่วไปค่าความจริงจะเป็นจริงทุกครั้งที่จำนวนตัวถูกดำเนินการจริงเป็นเลขคี่

ดังนั้นหากคุณกำลังค้นหาคำกริยา n-ary ที่เป็นจริงเมื่อตัวถูกดำเนินการตัวใดตัวหนึ่งเท่านั้นคุณอาจต้องการใช้:

def isOne(*vars):
    sum = False
    for v in vars:
        if sum and v:
            return False
        else:
            sum = sum or v
    return sum

สำหรับการปรับปรุงคำตอบนี้: (bool(False) is False) == True. คุณสามารถใช้Falseกับเส้นเหล่านั้น
pathunstrom

7

Exclusive หรือถูกกำหนดไว้ดังนี้

def xor( a, b ):
    return (a or b) and not (a and b)

2
ที่จะส่งคืนค่า True สำหรับ xor ('this', '') และเพื่อทำตามวิธีของ python มันควรจะคืนค่า 'this'
nosklo

@ nosklo: ทำมันด้วย BDFL ได้โปรดไม่ใช่ฉัน เนื่องจาก Python คืนค่าเป็น True ดังนั้นจึงต้องเป็นวิธีของ Python
S.Lott

2
ฉันหมายถึงความสอดคล้องกับตัวดำเนินการทางตรรกะอื่น ๆ ของ Python - Python จะไม่ส่งคืน True เมื่อฉัน ('this' หรือ '') มันส่งกลับ 'this' แต่ในฟังก์ชั่นของคุณ xor ('this', '') จะคืนค่าเป็น True ควรส่งคืน 'this' ตามที่ "หรือ" python builtin ทำ
nosklo

10
งูหลามandและorทำลัดวงจร xorการใช้งานใด ๆไม่สามารถทำให้เกิดไฟฟ้าลัดวงจรดังนั้นจึงมีความคลาดเคลื่อนอยู่แล้ว ดังนั้นจึงไม่มีเหตุผลที่xorควรใช้งานเช่นand+ orทำ
tzot

7

บางครั้งฉันพบว่าตัวเองทำงานกับ 1 และ 0 แทนค่าบูลีนจริงและเท็จ ในกรณีนี้ xor สามารถกำหนดเป็น

z = (x + y) % 2

ซึ่งมีตารางความจริงต่อไปนี้:

     x
   |0|1|
  -+-+-+
  0|0|1|
y -+-+-+
  1|1|0|
  -+-+-+

7

ฉันรู้ว่านี่สาย แต่ฉันมีความคิดและมันอาจจะคุ้มค่าสำหรับเอกสาร บางทีนี่อาจจะใช้ได้: np.abs(x-y)ความคิดก็คือ

  1. ถ้า x = True = 1 และ y = False = 0 ดังนั้นผลลัพธ์จะเป็น | 1-0 | = 1 = True
  2. ถ้า x = False = 0 และ y = False = 0 ดังนั้นผลลัพธ์จะเป็น | 0-0 | = 0 = False
  3. ถ้า x = True = 1 และ y = True = 1 ผลลัพธ์จะเป็น | 1-1 | = 0 = False
  4. ถ้า x = False = 0 และ y = True = 1 ดังนั้นผลลัพธ์จะเป็น | 0-1 | = 1 = True

7

ง่ายเข้าใจง่าย

sum( (bool(a), bool(b) ) == 1

หากตัวเลือกพิเศษคือสิ่งที่คุณต้องการคุณสามารถขยายไปยังหลาย ๆ อาร์กิวเมนต์ได้:

sum( bool(x) for x in y ) % 2 == 1

1
sum(map(bool, y)) % 2 == 1
warvariuc

6

แล้วเรื่องนี้ล่ะ

(not b and a) or (not a and b)

จะให้aถ้าbเป็นเท็จ
จะให้bถ้าaเป็นเท็จ
จะให้Falseอย่างอื่น

หรือด้วยนิพจน์ประกอบไปด้วย Python 2.5+:

(False if a else b) if b else a

6

การใช้งานบางอย่างที่แนะนำที่นี่จะทำให้การประเมินตัวถูกดำเนินการซ้ำ ๆ ในบางกรณีซึ่งอาจนำไปสู่ผลข้างเคียงที่ไม่ได้ตั้งใจดังนั้นจึงต้องหลีกเลี่ยง

ที่กล่าวว่าการ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()

5

คนจำนวนมากรวมถึงตัวฉันเองต้องการxorฟังก์ชั่นที่ทำงานเหมือนวงจร n-input xor ซึ่ง n เป็นตัวแปร (ดูhttps://en.wikipedia.org/wiki/XOR_gate ) ฟังก์ชั่นง่าย ๆ ต่อไปนี้ใช้สิ่งนี้

def xor(*args):
   """
   This function accepts an arbitrary number of input arguments, returning True
   if and only if bool() evaluates to True for an odd number of the input arguments.
   """

   return bool(sum(map(bool,args)) % 2)

ตัวอย่าง I / O ดังนี้

In [1]: xor(False, True)
Out[1]: True

In [2]: xor(True, True)
Out[2]: False

In [3]: xor(True, True, True)
Out[3]: True

5

ในการรับตรรกะ xor ของตัวแปรสองตัวขึ้นไปใน Python ให้ทำดังนี้

  1. แปลงอินพุตเป็นบูลีน
  2. ใช้ตัวดำเนินการ bitor xor ( ^หรือoperator.xor)

ตัวอย่างเช่น,

bool(a) ^ bool(b)

เมื่อคุณแปลงอินพุตเป็น booleans บิต xor จะกลายเป็นตรรกะ xor

โปรดทราบว่าคำตอบที่ยอมรับนั้นผิด: !=ไม่เหมือนกับ xor ใน Python เนื่องจากความซับซ้อนของการโยงผู้ปฏิบัติงานซับซ้อน

ตัวอย่างเช่น xor ของค่าทั้งสามด้านล่างไม่ถูกต้องเมื่อใช้!=:

True ^  False ^  False  # True, as expected of XOR
True != False != False  # False! Equivalent to `(True != False) and (False != False)`

(PS ฉันลองแก้ไขคำตอบที่ยอมรับเพื่อรวมคำเตือนนี้ แต่การเปลี่ยนแปลงของฉันถูกปฏิเสธ)



4

สิ่งนี้ได้รับ XOR แบบเอกสิทธิ์เฉพาะทางตรรกะสำหรับตัวแปรสองตัว (หรือมากกว่า)

str1 = raw_input("Enter string one:")
str2 = raw_input("Enter string two:")

any([str1, str2]) and not all([str1, str2])

ปัญหาแรกของการตั้งค่านี้คือมันเป็นไปได้มากที่จะสำรวจรายการทั้งหมดสองครั้งและอย่างน้อยที่สุดจะตรวจสอบองค์ประกอบอย่างน้อยหนึ่งรายการสองครั้ง ดังนั้นมันอาจเพิ่มความเข้าใจโค้ด แต่ไม่ได้ให้ยืมความเร็ว (ซึ่งอาจแตกต่างกันไปโดยไม่สนใจขึ้นอยู่กับกรณีการใช้งานของคุณ)

ปัญหาที่สองของการตั้งค่านี้คือการตรวจสอบการผูกขาดโดยไม่คำนึงถึงจำนวนของตัวแปร สิ่งนี้อาจถูกมองว่าเป็นคุณลักษณะในตอนแรก แต่ปัญหาแรกจะมีความสำคัญมากขึ้นเมื่อจำนวนของตัวแปรเพิ่มขึ้น (หากพวกเขาเคยทำ)


4

Xor อยู่^ใน Python มันกลับมา:

  • XOR ระดับบิตสำหรับ ints
  • Logor xor สำหรับ bools
  • ยูเนี่ยนพิเศษสำหรับชุด
  • ผลลัพธ์ที่ผู้ใช้กำหนดสำหรับคลาสที่ใช้งาน __xor__ผลลัพธ์ที่ผู้ใช้กำหนดไว้สำหรับชั้นเรียนที่ดำเนินการ
  • TypeError สำหรับประเภทที่ไม่ได้กำหนดเช่นสตริงหรือพจนานุกรม

หากคุณตั้งใจจะใช้มันในสายอักขระการใช้งานในการboolทำให้การดำเนินงานของคุณโปร่งใส (คุณอาจหมายถึงset(str1) ^ set(str2))



3

นี่คือวิธีที่ฉันจะเขียนตารางความจริงใด ๆ สำหรับ xor โดยเฉพาะเรามี:

| a | b  | xor   |             |
|---|----|-------|-------------|
| T | T  | F     |             |
| T | F  | T     | a and not b |
| F | T  | T     | not a and b |
| F | F  | F     |             |

เพียงแค่ดูค่า T ในคอลัมน์คำตอบและสตริงเข้าด้วยกันกรณีจริงทั้งหมดที่มีตรรกะหรือ ดังนั้นตารางความจริงนี้อาจเกิดขึ้นในกรณีที่ 2 หรือ 3 ดังนั้น

xor = lambda a, b: (a and not b) or (not a and b)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.