ทำไม tuples มีรายการที่ไม่แน่นอน


178

ถ้า tuple ไม่เปลี่ยนรูปแล้วทำไมมันถึงมีรายการที่เปลี่ยนแปลงได้?

ดูเหมือนจะขัดแย้งกันว่าเมื่อรายการที่ไม่แน่นอนเช่นรายการได้รับการแก้ไข tuple มันเป็นของการรักษาไม่เปลี่ยนรูป

คำตอบ:


205

นั่นเป็นคำถามที่ยอดเยี่ยม

ความเข้าใจที่สำคัญคือสิ่งอันดับทูเปิลไม่มีทางรู้ได้ว่าวัตถุที่อยู่ภายในนั้นไม่แน่นอนหรือไม่ สิ่งเดียวที่ทำให้วัตถุไม่แน่นอนคือการมีวิธีการเปลี่ยนแปลงข้อมูล โดยทั่วไปไม่มีวิธีตรวจจับสิ่งนี้

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

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

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

  1. สิ่งอันดับ Tuples มีความโดดเด่นน้อยลงเนื่องจากความไม่สามารถเปลี่ยนแปลงได้และอื่น ๆ ตามวัตถุประสงค์ที่ตั้งใจไว้
    Tuples เป็นวิธีการรวบรวมข้อมูลต่าง ๆ ของ Python ภายใต้หลังคาเดียวกัน ตัวอย่างเช่น s = ('www.python.org', 80) รวบรวมสตริงและตัวเลขเพื่อให้คู่โฮสต์ / พอร์ตสามารถส่งผ่านเป็นซ็อกเก็ตซึ่งเป็นวัตถุประกอบ เมื่อมองในแง่ของแสงแล้วมันก็สมเหตุสมผลอย่างสมบูรณ์แบบที่จะมีส่วนประกอบที่ไม่แน่นอน

  2. เปลี่ยนไม่ได้ไปมือในมือที่มีคุณสมบัติอื่นhashability แต่ hashability ไม่ใช่คุณสมบัติที่สมบูรณ์ หากหนึ่งในองค์ประกอบของ tuple นั้นไม่สามารถแฮชได้ดังนั้น tuple โดยรวมก็ไม่สามารถแฮชได้เช่นกัน ตัวอย่างเช่นt = ('red', [10, 20, 30])ไม่แฮช

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

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

หวังว่านี่จะเป็นประโยชน์กับคุณ :-)


ไม่ผิดหรอก "ทูเปิลไม่มีทางรู้ว่าวัตถุที่อยู่ในนั้นไม่แน่นอน" เราสามารถตรวจสอบได้ว่าการอ้างอิงนั้นใช้วิธีแฮชหรือไม่ เช่นเดียวกับ dic หรือชุดจะทำ นี่จะเป็นการตัดสินใจออกแบบมากกว่านี้สำหรับสิ่งอันดับทูเปิลหรือไม่?
garg10may

@ garg10may 1) ความสามารถในการแฮชไม่สามารถตรวจพบได้โดยไม่ต้องโทรhash()เพราะทุกอย่างที่สืบทอดจากobject ()นั้นสามารถแฮชได้ดังนั้นคลาสย่อยจึงจำเป็นต้องปิดการแฮชอย่างชัดแจ้ง 2) Hashibility ไม่รับประกันความไม่สามารถเปลี่ยนได้ - มันง่ายที่จะทำตัวอย่างของวัตถุที่สับได้ที่ไม่แน่นอน 3) Tuples เช่นคอนเทนเนอร์ส่วนใหญ่ใน Python เพียงแค่มีการอ้างอิงไปยังวัตถุต้นแบบ - พวกเขาไม่มีหน้าที่ตรวจสอบและทำการอ้างถึงพวกมัน
Raymond Hettinger

171

นั่นเป็นเพราะสิ่งอันดับไม่มีรายการสตริงหรือตัวเลข พวกเขามีการอ้างอิงถึงวัตถุอื่น1การไม่สามารถเปลี่ยนลำดับของการอ้างอิงที่มี tuple นั้นไม่ได้หมายความว่าคุณไม่สามารถกลายพันธุ์วัตถุที่เกี่ยวข้องกับการอ้างอิงเหล่านั้นได้ 2

1. วัตถุค่าและประเภท (ดู: สองย่อหน้าสุดท้าย)
2. ลำดับชั้นประเภทมาตรฐาน (ดู: "ลำดับไม่เปลี่ยนรูป")


8
มีความคลุมเครือในคำถาม คำตอบนี้อธิบายอย่างเต็มที่ว่าทำไมจึงเป็นไปได้ที่ทูเปิลจะมีวัตถุที่ไม่แน่นอน ไม่ได้อธิบายว่าทำไม tuples ได้รับการออกแบบให้มีวัตถุที่ไม่แน่นอน ฉันคิดว่าคำถามหลังนี้เป็นคำถามที่เกี่ยวข้องมากกว่า
senderle

16

ก่อนอื่นคำว่า "ไม่เปลี่ยนรูป" อาจหมายถึงสิ่งต่าง ๆ มากมายสำหรับคนที่แตกต่างกัน โดยเฉพาะอย่างยิ่งผมชอบวิธี Eric Lippert แบ่งไม่เปลี่ยนรูปในโพสต์บล็อกของเขา ที่นั่นเขาแสดงรายการประเภทไม่เปลี่ยนรูปแบบเหล่านี้:

  • ความไม่สามารถเปลี่ยนแปลงได้อย่างแท้จริง
  • การเปลี่ยนไม่ได้เขียนครั้งเดียว
  • ไอติมไม่เปลี่ยนรูป
  • Shallow vs immutability ที่ลึกล้ำ
  • อาคารที่ไม่เปลี่ยนรูป
  • การสังเกตการณ์ไม่เปลี่ยนรูป

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

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


Python tuples มีชนิดใดที่ไม่สามารถเปลี่ยนแปลงได้?
qazwsx

3
Python tuples มีความผันแปรไม่ได้ (หรือที่เรียกว่า non-transitive)
Ken Wayne VanderLinde

16

ตามที่ฉันเข้าใจแล้วคำถามนี้จำเป็นต้องถูกนำมาใช้ใหม่เป็นคำถามเกี่ยวกับการตัดสินใจในการออกแบบ: ทำไมนักออกแบบของ Python จึงเลือกที่จะสร้างประเภทลำดับที่ไม่เปลี่ยนรูปซึ่งสามารถมีวัตถุที่ไม่แน่นอนได้

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

  1. Tuples นั้นเร็วและมีประสิทธิภาพของหน่วยความจำ: Tuples นั้นสร้างได้เร็วกว่ารายการเพราะมันไม่เปลี่ยนรูป เปลี่ยนไม่ได้หมายความว่า tuples สามารถสร้างเป็นค่าคงที่และเต็มไปเช่นนี้โดยใช้การพับอย่างต่อเนื่อง นอกจากนี้ยังหมายความว่าพวกเขาสร้างได้เร็วขึ้นและมีหน่วยความจำที่มีประสิทธิภาพมากขึ้นเนื่องจากไม่จำเป็นต้องใช้สถานที่โดยรวม ฯลฯช้ากว่ารายการสำหรับการเข้าถึงรายการแบบสุ่ม แต่เร็วกว่าสำหรับการเปิดกล่องบรรจุ (อย่างน้อยในเครื่องของฉัน) ถ้าสิ่งอันดับเป็นสิ่งที่ไม่แน่นอนพวกเขาจะไม่เร็วสำหรับจุดประสงค์เช่นนี้

  2. Tuples เป็นจุดประสงค์ทั่วไป : Tuples จะต้องสามารถบรรจุวัตถุชนิดใดก็ได้ พวกมันคุ้นเคยกับ (ทำอย่างรวดเร็ว) ทำสิ่งต่าง ๆ เช่นรายการอาร์กิวเมนต์ความยาวผันแปร (ผ่าน*โอเปอเรเตอร์ในนิยามฟังก์ชัน) หากทูเปิลไม่สามารถถือวัตถุที่ไม่แน่นอนได้พวกมันคงไร้ประโยชน์สำหรับสิ่งนี้ Python จะต้องใช้รายการซึ่งอาจทำให้รายการช้าลงและจะมีประสิทธิภาพของหน่วยความจำน้อยลงอย่างแน่นอน

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


12

คุณไม่สามารถเปลี่ยนรายการidของมัน ดังนั้นมันจะมีรายการเดียวกันเสมอ

$ python
>>> t = (1, [2, 3])
>>> id(t[1])
12371368
>>> t[1].append(4)
>>> id(t[1])
12371368

นี่เป็นการสาธิตที่เหมาะสมที่สุดของตัวอย่างข้างต้น Tuple มีการอ้างอิงไปยังวัตถุเหล่านั้นซึ่งไม่เปลี่ยนแปลงแม้ว่าจะมีส่วนประกอบที่ไม่แน่นอนอย่างน้อยหนึ่งองค์ประกอบที่ทำให้ tuple ทั้งหมดไม่สามารถล้างได้
piepi

5

ฉันจะไปบนกิ่งก้านที่นี่และบอกว่าส่วนที่เกี่ยวข้องที่นี่คือว่าในขณะที่คุณสามารถเปลี่ยนเนื้อหาของรายการหรือสถานะของวัตถุที่มีอยู่ภายในขอบเขตของสิ่งที่คุณไม่สามารถเปลี่ยนแปลงเป็นที่วัตถุ หรือรายการอยู่ที่นั่น หากคุณมีบางอย่างที่ขึ้นอยู่กับสิ่งที่ [3] เป็นรายการแม้ว่าจะว่างเปล่าฉันก็จะเห็นว่าสิ่งนี้มีประโยชน์


3

เหตุผลหนึ่งคือไม่มีวิธีทั่วไปใน Python ในการแปลงประเภทที่ไม่แน่นอนให้เป็นประเภทที่ไม่เปลี่ยนรูป (ดูPEP 351 ที่ถูกปฏิเสธและการอภิปรายที่เชื่อมโยงถึงสาเหตุที่ถูกปฏิเสธ) ดังนั้นจึงเป็นไปไม่ได้ที่จะวางวัตถุประเภทต่าง ๆ ในสิ่งอันดับถ้ามันมีข้อ จำกัด นี้รวมถึงวัตถุที่ผู้ใช้สร้างขึ้นไม่ได้

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


2

tuple นั้นไม่สามารถเปลี่ยนแปลงได้ในแง่ที่ว่า tuple นั้นไม่สามารถขยายหรือหดตัวได้ไม่ใช่ว่าสิ่งของทุกอย่างที่บรรจุอยู่นั้นจะไม่เปลี่ยนรูป มิฉะนั้นสิ่งอันดับจะน่าเบื่อ

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