รายการที่ซ้ำกันอีกรายการหนึ่งถามว่าทำไมโดยทั่วไปสองสตริงที่เท่ากันจึงไม่เหมือนกันซึ่งยังไม่มีคำตอบที่นี่:
>>> x = 'a'
>>> x += 'bc'
>>> y = 'abc'
>>> x == y
True
>>> x is y
False
แล้วทำไมมันไม่เหมือนกันล่ะ? โดยเฉพาะอย่างยิ่งสิ่งนี้:
>>> z = 'abc'
>>> w = 'abc'
>>> z is w
True
ขอปิดส่วนที่สองสักหน่อย คนแรกจะเป็นจริงได้อย่างไร?
ล่ามจะต้องมี "interning table" ซึ่งเป็นค่าสตริงการแม็ปตารางกับสตริงอ็อบเจ็กต์ดังนั้นทุกครั้งที่คุณพยายามสร้างสตริงใหม่พร้อมเนื้อหา'abc'
คุณจะได้รับอ็อบเจกต์เดียวกันกลับคืนมา Wikipediaมีการอภิปรายรายละเอียดเพิ่มเติมเกี่ยวกับวิธีการฝึกงาน
และ Python มีตารางภายในสตริง คุณสามารถฝึกสตริงด้วยตนเองด้วยsys.intern
วิธีการ
ในความเป็นจริง Python ได้รับอนุญาตให้ควบคุมประเภทที่ไม่เปลี่ยนรูปได้โดยอัตโนมัติ แต่ไม่จำเป็นต้องทำเช่นนั้น การใช้งานที่แตกต่างกันจะทำให้เกิดคุณค่าที่แตกต่างกัน
CPython (การใช้งานที่คุณใช้หากคุณไม่ทราบว่าคุณกำลังใช้การนำไปใช้งานใด) auto-interns จำนวนเต็มขนาดเล็กและ singletons พิเศษบางอย่างเช่นFalse
แต่ไม่ใช่สตริง (หรือจำนวนเต็มขนาดใหญ่หรือสิ่งที่มีขนาดเล็กหรือสิ่งอื่นใด) คุณสามารถเห็นสิ่งนี้ได้อย่างง่ายดาย:
>>> a = 0
>>> a += 1
>>> b = 1
>>> a is b
True
>>> a = False
>>> a = not a
>>> b = True
a is b
True
>>> a = 1000
>>> a += 1
>>> b = 1001
>>> a is b
False
OK แต่ทำไมอยู่z
และw
ที่เหมือนกัน?
นั่นไม่ใช่ล่ามโดยอัตโนมัติภายในนั่นคือค่าการพับของคอมไพเลอร์
ถ้าสตริงรวบรวมเวลาเดียวกันปรากฏขึ้นเป็นครั้งที่สองในโมดูลเดียวกัน (สิ่งที่ว่านี้หมายถึงเป็นเรื่องยากที่จะกำหนดมันไม่ได้เป็นสิ่งเดียวกับตัวอักษรสตริงเพราะr'abc'
, 'abc'
และ'a' 'b' 'c'
มีตัวอักษรที่แตกต่างกันทั้งหมด แต่เดียวกันสตริง แต่ง่ายต่อการเข้าใจ โดยสัญชาตญาณ) คอมไพเลอร์จะสร้างสตริงเพียงหนึ่งอินสแตนซ์โดยมีการอ้างอิงสองรายการ
ในความเป็นจริงคอมไพเลอร์สามารถไปได้ไกลกว่า'ab' + 'c'
นั้น: สามารถแปลงเป็นได้'abc'
โดยเครื่องมือเพิ่มประสิทธิภาพซึ่งในกรณีนี้สามารถพับพร้อมกับ'abc'
ค่าคงที่ในโมดูลเดียวกันได้
อีกครั้งนี่เป็นสิ่งที่อนุญาตให้ใช้ Python แต่ไม่จำเป็นต้องทำ แต่ในกรณีนี้ CPython จะพับสตริงเล็ก ๆ เสมอ (และเช่นสิ่งที่มีขนาดเล็ก) (แม้ว่าคอมไพลเลอร์คำสั่งต่อคำสั่งของล่ามแบบโต้ตอบจะไม่เรียกใช้การปรับให้เหมาะสมเช่นเดียวกับคอมไพเลอร์โมดูลในแต่ละครั้งดังนั้นคุณจะไม่เห็นผลลัพธ์เดียวกันในเชิงโต้ตอบ)
แล้วคุณควรทำอย่างไรกับเรื่องนี้ในฐานะโปรแกรมเมอร์?
อืม…ไม่มีอะไร คุณแทบไม่มีเหตุผลใด ๆ ที่จะต้องสนใจว่าค่าที่ไม่เปลี่ยนรูปสองค่าจะเหมือนกันหรือไม่ หากคุณต้องการทราบว่าคุณสามารถใช้a is b
แทนได้เมื่อa == b
ใดคุณกำลังถามคำถามผิด ใช้เสมอa == b
ยกเว้นในสองกรณี:
- สำหรับการเปรียบเทียบที่อ่านได้เพิ่มเติมกับค่าซิงเกิลตันเช่น
x is None
.
- สำหรับค่าที่ไม่แน่นอนเมื่อคุณต้องการทราบว่าการกลายพันธุ์
x
จะส่งผลต่อไฟล์y
.