เปรียบเทียบว่าตัวแปรสองตัวอ้างอิงวัตถุเดียวกันใน python หรือไม่


95

วิธีตรวจสอบว่าสองตัวแปรอ้างอิงวัตถุเดียวกันหรือไม่?

x = ['a', 'b', 'c']
y = x                 # x and y reference the same object
z = ['a', 'b', 'c']   # x and z reference different objects

คำตอบ:


134

นั่นคือสิ่งที่isมีไว้สำหรับ: x is yส่งกลับTrueif xและyเป็นวัตถุเดียวกัน


6
ในตัวอย่างผลตอบแทนx is z Falseแต่ถ้า x z และมีการกำหนดค่าเดียวกันแทนของรายการ (ตัวอย่างx, z = 13, 13) แล้วผลตอบแทนx is z Trueทำไมถึงเป็นเช่นนั้น?
บิล

12
@ บิล: นั่นคือสิ่งประดิษฐ์ของวิธีที่ python จัดการกับ ints Python จัดสรรอ็อบเจ็กต์จำนวนเต็มไปที่xและzชี้ เนื่องจากจำนวนเต็มขนาดเล็กเป็นความล้มเหลวทั่วไป (-1 เป็นค่าความผิดพลาด 0 เมื่อใดก็ตามที่คุณทำดัชนีบางสิ่งตัวเลขขนาดเล็กมักเป็นค่าเริ่มต้นที่สมเหตุสมผล) Python ปรับให้เหมาะสมโดยการจัดสรรตัวเลขขนาดเล็กล่วงหน้า (-5 ถึง 256) และใช้วัตถุจำนวนเต็มเดียวกันซ้ำ ดังนั้นตัวอย่างของคุณจึงใช้ได้กับตัวเลขในช่วงนี้เท่านั้น 270ลองกำหนดบางสิ่งบางอย่างที่มีขนาดใหญ่เช่น ดูข้อมูลเพิ่มเติมได้ที่นี่
ted

1
@AndresR ไม่ว่าผิด isตรวจสอบว่าสองชื่ออ้างอิงตำแหน่งหน่วยความจำเดียวกันหรือไม่ มันไม่มีอะไรเกี่ยวข้องกับตัววัตถุ เป็นเรื่องง่ายที่จะมีวัตถุที่ไม่เปลี่ยนรูปแบบเช่นสตริงที่เท่ากัน แต่ไม่ได้เก็บไว้ที่ตำแหน่งเดียวกันตัวอย่างเช่น''a'*10000 is 'a' * 10000False
Jochen Ritzel

1
@JochenRitzel คุณพูดถูกต้องขอบคุณสำหรับความคิดเห็นนี้! ถ้าอย่างนั้นฉันไม่เข้าใจว่าเกิดอะไรขึ้น"af" is "af"หรือ() is ()... ทำไมพวกเขาถึงแชร์ตำแหน่งหน่วยความจำเดียวกัน
AndresR

2
@AndreasR สำหรับสตริง / ตัวเลขตามตัวอักษรในโค้ดคอมไพลเลอร์จะตรวจสอบว่ามีอยู่เพียงครั้งเดียวและนำกลับมาใช้ใหม่ ค่าพิเศษเช่น (), None, True, False ฯลฯ ถูกกำหนดให้เป็น singletons ด้วย ในระหว่างการดำเนินการรันไทม์ยังพยายามนำตัวเลขและสตริงขนาดเล็กกลับมาใช้ใหม่ แต่ในท้ายที่สุดการแลกเปลี่ยนระหว่างความเร็วกับหน่วยความจำและสิ่งที่เกิดขึ้นนั้นขึ้นอยู่กับวิธีการใช้งานรันไทม์ของ Python
Jochen Ritzel


11

คุณยังสามารถใช้id ()เพื่อตรวจสอบว่าออบเจ็กต์เฉพาะที่แต่ละชื่อตัวแปรอ้างถึง

In [1]: x1, x2 = 'foo', 'foo'

In [2]: x1 == x2
Out[2]: True

In [3]: id(x1), id(x2)
Out[3]: (4509849040, 4509849040)

In [4]: x2 = 'foobar'[0:3]

In [5]: x2
Out[5]: 'foo'

In [6]: x1 == x2
Out[6]: True

In [7]: x1 is x2
Out[7]: False

In [8]: id(x1), id(x2)
Out[8]: (4509849040, 4526514944)

หมายเหตุของ @ ted เกี่ยวกับการใช้ id ค่อนข้างเกี่ยวข้องที่นี่
Leo Ufimtsev

11

ในขณะที่สองวิธีแก้ไขที่ถูกต้องx is zและid(x) == id(z)ได้รับการโพสต์แล้วฉันต้องการชี้ให้เห็นรายละเอียดการใช้งานของ python Python จัดเก็บจำนวนเต็มเป็นวัตถุเนื่องจากการเพิ่มประสิทธิภาพจะสร้างจำนวนเต็มขนาดเล็กจำนวนมากเมื่อเริ่มต้น (-5 ถึง 256) และชี้ตัวแปรทุกตัวที่ถือจำนวนเต็มที่มีค่าเล็กน้อยไปยังวัตถุที่กำหนดค่าเริ่มต้นเหล่านี้ ข้อมูลเพิ่มเติม

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

> i = 13
> j = 13
> i is j
True

> a = 280
> b = 280
> a is b
False

> a = b
> a
280
> a is b
True

python3.6: a = 98765; ข = 98765; a คือ b => จริง มีบางอย่างเปลี่ยนไปอย่างเห็นได้ชัด
Mikhail Kalashnikov

@MikhailKalashnikov Nope. ฉันทดสอบกับ Python 3.6.2 สิ่งนี้ยังคงมีอยู่
nix

ยังคงมีอยู่ใน python 3.7.7
Bill Huang

2

ฉันชอบที่จะได้รับความคิดเห็นที่เป็นภาพนั่นเป็นเหตุผลว่าทำไมบางครั้งฉันจึงเปิดhttp://www.pythontutor.com/visualize.html#mode=editเพื่อดูว่าหน่วยความจำได้รับการจัดสรรอย่างไรและสิ่งที่อ้างอิงถึงอะไร

ป้อนคำอธิบายภาพที่นี่

เพิ่ม GIF ที่ยอดเยี่ยมนี้เนื่องจากคำตอบนี้เกี่ยวกับการแสดงภาพ ..


2

สิ่งนี้มาจาก docs.python.org: "ทุกออบเจ็กต์มีตัวตนประเภทและค่าเอกลักษณ์ของอ็อบเจ็กต์ไม่เคยเปลี่ยนแปลงเมื่อถูกสร้างขึ้นคุณอาจคิดว่ามันเป็นแอดเดรสของอ็อบเจ็กต์ในหน่วยความจำตัวดำเนินการ 'is' เปรียบเทียบเอกลักษณ์ของวัตถุสองชิ้นฟังก์ชัน id () จะส่งคืนจำนวนเต็มที่แสดงถึงเอกลักษณ์ของมัน "

เห็นได้ชัดว่าทุกครั้งที่คุณเปลี่ยนค่าวัตถุจะถูกสร้างขึ้นใหม่ตามที่ระบุโดยเอกลักษณ์ที่เปลี่ยนไป บรรทัด x = 3 ตามด้วยเส้น x = 3.14 ไม่มีข้อผิดพลาดและให้ข้อมูลประจำตัวประเภทและค่าที่แตกต่างกันสำหรับ x


1
จับเอกสารได้ดีเยี่ยม
prosti

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