มีความแตกต่างระหว่าง==และisใน Python หรือไม่?
ใช่พวกเขามีความแตกต่างที่สำคัญมาก
==: ตรวจสอบความเท่าเทียมกัน - ความหมายคือวัตถุที่เทียบเท่ากัน (ซึ่งไม่จำเป็นต้องเป็นวัตถุเดียวกัน) จะทดสอบเท่ากัน ตามเอกสารระบุว่า :
ตัวดำเนินการ <,>, ==,> =, <= และ! = เปรียบเทียบค่าของวัตถุสองชนิด
is: ตรวจสอบตัวตน - ความหมายคือวัตถุ (ตามที่เก็บไว้ในหน่วยความจำ) เป็นวัตถุ อีกครั้งเอกสารกล่าวว่า :
โอเปอเรเตอร์isและis notทดสอบการระบุตัวตนของวัตถุ: x is yเป็นจริงหากและถ้าxและyเป็นวัตถุเดียวกันเท่านั้น เอกลักษณ์ของวัตถุถูกกำหนดโดยใช้id()ฟังก์ชัน x is not yให้ค่าความจริงผกผัน
ดังนั้นการตรวจสอบเอกลักษณ์จึงเหมือนกับการตรวจสอบความเสมอภาคของ ID ของวัตถุ นั่นคือ,
a is b
เหมือนกับ:
id(a) == id(b)
โดยที่idฟังก์ชันบิวอินจะส่งกลับจำนวนเต็มว่า "รับประกันว่าจะไม่ซ้ำกันระหว่างวัตถุที่มีอยู่พร้อมกัน" (ดูhelp(id)) และที่ไหนaและbเป็นวัตถุใด ๆ
ทิศทางการใช้งานอื่น ๆ
คุณควรใช้การเปรียบเทียบเหล่านี้สำหรับความหมายของพวกเขา ใช้isเพื่อตรวจสอบตัวตนและ==เพื่อตรวจสอบความเท่าเทียมกัน
ดังนั้นโดยทั่วไปเราใช้isเพื่อตรวจสอบตัวตน โดยปกติจะมีประโยชน์เมื่อเรากำลังตรวจสอบวัตถุที่ควรมีอยู่เพียงครั้งเดียวในหน่วยความจำซึ่งเรียกว่า "ซิงเกิล" ในเอกสารประกอบ
ใช้กรณีisรวมถึง:
None
- ค่า enum (เมื่อใช้ Enums จากโมดูล enum)
- โมดูลมักจะ
- มักจะเป็นวัตถุคลาสที่เกิดจากคำจำกัดความของชั้นเรียน
- ฟังก์ชั่นมักจะเป็นวัตถุที่เกิดจากการกำหนดฟังก์ชั่น
- สิ่งอื่นใดที่ควรมีอยู่ครั้งเดียวในหน่วยความจำ (singletons ทั้งหมดโดยทั่วไป)
- วัตถุเฉพาะที่คุณต้องการด้วยตัวตน
กรณีการใช้งานปกติสำหรับ==รวมถึง:
- ตัวเลขรวมถึงจำนวนเต็ม
- เงื่อนไข
- รายการ
- ชุด
- พจนานุกรม
- วัตถุที่ไม่แน่นอนที่กำหนดเอง
- วัตถุที่ไม่เปลี่ยนรูปอื่น ๆ ในตัวส่วนใหญ่
กรณีการใช้งานทั่วไปอีกครั้ง==เป็นวัตถุที่คุณต้องการอาจจะไม่เหมือนกันวัตถุ แต่มันอาจจะเป็นเทียบเท่าหนึ่ง
PEP 8 ทิศทาง
PEP 8 คู่มือสไตล์ Python อย่างเป็นทางการสำหรับไลบรารี่มาตรฐานยังกล่าวถึงกรณีใช้งานสองกรณีสำหรับis :
การเปรียบเทียบกับแบบซิงเกิลNoneควรทำด้วยเสมอisหรือ
is notไม่ควรใช้ตัวดำเนินการที่เท่าเทียมกัน
นอกจากนี้ระวังการเขียนif xเมื่อคุณหมายถึงif x is not None- เช่นเมื่อทดสอบว่าตัวแปรหรืออาร์กิวเมนต์ที่ค่าเริ่มต้นNone
ถูกตั้งค่าเป็นค่าอื่น ค่าอื่นอาจมีประเภท (เช่นภาชนะ) ที่อาจเป็นเท็จในบริบทบูลีน!
การอนุมานความเสมอภาคจากตัวตน
ถ้าisเป็นจริงความเท่าเทียมกันมักจะอนุมานได้ - อย่างมีเหตุผลถ้าวัตถุเป็นของตัวเองมันก็ควรทดสอบว่าเทียบเท่ากับตัวมันเอง
ในกรณีส่วนใหญ่ตรรกะนี้เป็นจริง แต่ขึ้นอยู่กับการดำเนินการตาม__eq__วิธีพิเศษ อย่างที่เอกสารพูด
พฤติกรรมเริ่มต้นสำหรับการเปรียบเทียบความเท่าเทียมกัน ( ==และ!=) ขึ้นอยู่กับตัวตนของวัตถุ ดังนั้นการเปรียบเทียบความเท่าเทียมกันของอินสแตนซ์ที่มีตัวตนเดียวกันส่งผลให้เกิดความเท่าเทียมกันและการเปรียบเทียบความเท่าเทียมกันของอินสแตนซ์ที่มีตัวตนที่แตกต่างกันส่งผลให้เกิดความไม่เท่าเทียมกัน แรงจูงใจสำหรับพฤติกรรมเริ่มต้นนี้คือความปรารถนาที่วัตถุทั้งหมดควรสะท้อนกลับ (เช่น x คือ y หมายถึง x == y)
และเพื่อประโยชน์ของความมั่นคงแนะนำ:
การเปรียบเทียบความเท่าเทียมควรสะท้อนกลับ ในคำอื่น ๆ วัตถุที่เหมือนกันควรเปรียบเทียบเท่ากัน:
x is y หมายถึง x == y
เราจะเห็นว่านี่เป็นพฤติกรรมเริ่มต้นสำหรับวัตถุที่กำหนดเอง:
>>> class Object(object): pass
>>> obj = Object()
>>> obj2 = Object()
>>> obj == obj, obj is obj
(True, True)
>>> obj == obj2, obj is obj2
(False, False)
contrapositive ก็มักจะเป็นจริงเช่นกัน - หากการทดสอบบางสิ่งไม่เท่ากันคุณสามารถอนุมานได้ว่าสิ่งนั้นไม่ใช่วัตถุเดียวกัน
เนื่องจากสามารถทำการทดสอบเพื่อความเท่าเทียมกันได้การอนุมานนี้จึงไม่ถือเป็นจริงสำหรับทุกประเภท
ข้อยกเว้น
ข้อยกเว้นที่น่าสังเกตคือnan- มันจะทำการทดสอบเสมอไม่เท่ากับตัวมัน
>>> nan = float('nan')
>>> nan
nan
>>> nan is nan
True
>>> nan == nan # !!!!!
False
การตรวจสอบข้อมูลประจำตัวอาจเป็นการตรวจสอบที่รวดเร็วกว่าการตรวจสอบความเท่าเทียมกัน (ซึ่งอาจต้องมีการตรวจสอบสมาชิกซ้ำ)
แต่ไม่สามารถทดแทนเพื่อความเท่าเทียมกันซึ่งคุณอาจพบวัตถุมากกว่าหนึ่งรายการที่เทียบเท่า
โปรดทราบว่าการเปรียบเทียบความเท่าเทียมกันของรายการและสิ่งอันดับจะถือว่าความเป็นตัวตนของวัตถุเท่ากัน (เพราะเป็นการตรวจสอบที่รวดเร็ว) สิ่งนี้สามารถสร้างความขัดแย้งได้ถ้าลอจิกนั้นไม่สอดคล้องกันซึ่งมีไว้สำหรับnan:
>>> [nan] == [nan]
True
>>> (nan,) == (nan,)
True
เรื่องเตือน:
คำถามกำลังพยายามใช้isเพื่อเปรียบเทียบจำนวนเต็ม คุณไม่ควรสมมติว่าอินสแตนซ์ของจำนวนเต็มเป็นอินสแตนซ์เดียวกับที่ได้รับจากการอ้างอิงอื่น เรื่องนี้อธิบายว่าทำไม
ผู้แสดงความคิดเห็นมีรหัสที่อาศัยความจริงที่ว่าจำนวนเต็มขนาดเล็ก (-5 ถึง 256 รวม) เป็น singletons ใน Python แทนที่จะตรวจสอบความเท่าเทียมกัน
ว้าวนี่อาจนำไปสู่ข้อบกพร่องที่ร้ายกาจ ฉันมีรหัสบางอย่างที่ตรวจสอบว่า a คือ b ซึ่งทำงานได้ตามที่ฉันต้องการเพราะ a และ b มักเป็นจำนวนน้อย ข้อผิดพลาดเกิดขึ้นในวันนี้หลังจากผ่านไปหกเดือนในการผลิตเพราะในที่สุด a และ b นั้นมีขนาดใหญ่พอที่จะไม่ถูกแคช - gwg
มันทำงานในการพัฒนา มันอาจจะผ่านการไม่เห็นด้วย
และมันใช้งานได้จริง - จนกระทั่งโค้ดตรวจสอบว่าเป็นจำนวนเต็มที่มากกว่า 256 ณ จุดนั้นมันล้มเหลวในการผลิต
นี่คือความล้มเหลวในการผลิตที่อาจติดอยู่ในการตรวจสอบโค้ดหรืออาจเป็นกับตัวตรวจสอบสไตล์
ผมขอเน้น: อย่าใช้isเพื่อเปรียบเทียบจำนวนเต็ม
echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - fooผลลัพธ์:False True False.