ถ้า tuple ไม่เปลี่ยนรูปแล้วทำไมมันถึงมีรายการที่เปลี่ยนแปลงได้?
ดูเหมือนจะขัดแย้งกันว่าเมื่อรายการที่ไม่แน่นอนเช่นรายการได้รับการแก้ไข tuple มันเป็นของการรักษาไม่เปลี่ยนรูป
ถ้า tuple ไม่เปลี่ยนรูปแล้วทำไมมันถึงมีรายการที่เปลี่ยนแปลงได้?
ดูเหมือนจะขัดแย้งกันว่าเมื่อรายการที่ไม่แน่นอนเช่นรายการได้รับการแก้ไข tuple มันเป็นของการรักษาไม่เปลี่ยนรูป
คำตอบ:
นั่นเป็นคำถามที่ยอดเยี่ยม
ความเข้าใจที่สำคัญคือสิ่งอันดับทูเปิลไม่มีทางรู้ได้ว่าวัตถุที่อยู่ภายในนั้นไม่แน่นอนหรือไม่ สิ่งเดียวที่ทำให้วัตถุไม่แน่นอนคือการมีวิธีการเปลี่ยนแปลงข้อมูล โดยทั่วไปไม่มีวิธีตรวจจับสิ่งนี้
ข้อมูลเชิงลึกอีกประการหนึ่งคือภาชนะของ Python ไม่มีอะไรบรรจุอยู่จริง แต่จะอ้างอิงถึงวัตถุอื่นแทน ตัวแปรของ Python ไม่เหมือนกับตัวแปรในภาษาที่คอมไพล์ แต่ชื่อตัวแปรเป็นเพียงคีย์ในพจนานุกรมเนมสเปซที่เกี่ยวข้องกับวัตถุที่สอดคล้องกัน เน็ดแบทช์เฮลเดอร์อธิบายเรื่องนี้ในบล็อกโพสต์ของเขา ไม่ว่าจะด้วยวิธีใดวัตถุจะรู้ได้เพียงจำนวนการอ้างอิงเท่านั้น พวกเขาไม่ทราบว่าการอ้างอิงเหล่านั้นคืออะไร (ตัวแปรคอนเทนเนอร์หรือ Python ภายใน)
ข้อมูลเชิงลึกทั้งสองนี้อธิบายความลึกลับของคุณ (ทำไม tuple ที่ไม่เปลี่ยนรูป "ที่มี" รายการดูเหมือนจะเปลี่ยนเมื่อรายการพื้นฐานเปลี่ยนแปลง) ในความเป็นจริง tuple ไม่เปลี่ยนแปลง (มันยังคงมีการอ้างอิงเดียวกันกับวัตถุอื่น ๆ ที่เคยทำมาก่อน) tuple ไม่สามารถเปลี่ยนแปลงได้ (เพราะไม่มีวิธีการกลายพันธุ์) เมื่อรายการเปลี่ยนแปลง tuple ไม่ได้รับการแจ้งเตือนการเปลี่ยนแปลง (รายการไม่ทราบว่าตัวแปรถูกอ้างถึงโดย tuple หรือรายการอื่น)
ในขณะที่เราอยู่ในหัวข้อต่อไปนี้เป็นความคิดอื่น ๆ ที่จะช่วยให้แบบจำลองทางจิตของคุณสมบูรณ์ว่าทูเปิลคืออะไรทำงานอย่างไรและใช้งานอย่างไร:
สิ่งอันดับ Tuples มีความโดดเด่นน้อยลงเนื่องจากความไม่สามารถเปลี่ยนแปลงได้และอื่น ๆ ตามวัตถุประสงค์ที่ตั้งใจไว้
Tuples เป็นวิธีการรวบรวมข้อมูลต่าง ๆ ของ Python ภายใต้หลังคาเดียวกัน ตัวอย่างเช่น
s = ('www.python.org', 80)
รวบรวมสตริงและตัวเลขเพื่อให้คู่โฮสต์ / พอร์ตสามารถส่งผ่านเป็นซ็อกเก็ตซึ่งเป็นวัตถุประกอบ เมื่อมองในแง่ของแสงแล้วมันก็สมเหตุสมผลอย่างสมบูรณ์แบบที่จะมีส่วนประกอบที่ไม่แน่นอน
เปลี่ยนไม่ได้ไปมือในมือที่มีคุณสมบัติอื่นhashability แต่ hashability ไม่ใช่คุณสมบัติที่สมบูรณ์ หากหนึ่งในองค์ประกอบของ tuple นั้นไม่สามารถแฮชได้ดังนั้น tuple โดยรวมก็ไม่สามารถแฮชได้เช่นกัน ตัวอย่างเช่นt = ('red', [10, 20, 30])
ไม่แฮช
ตัวอย่างสุดท้ายแสดง 2-tuple ที่มีสตริงและรายการ tuple นั้นไม่สามารถเปลี่ยนแปลงได้ (เช่นไม่มีวิธีใดในการเปลี่ยนเนื้อหา) สตริงจะไม่เปลี่ยนรูปเนื่องจากสตริงไม่มีวิธีการกลายพันธุ์ใด ๆ วัตถุรายการมีวิธีการกลายพันธุ์ดังนั้นจึงสามารถเปลี่ยนแปลงได้ สิ่งนี้แสดงให้เห็นว่าความไม่แน่นอนนั้นเป็นคุณสมบัติของชนิดวัตถุ - วัตถุบางอย่างมีวิธีการกลายพันธุ์และบางอย่างก็ไม่ทำเช่นนั้น สิ่งนี้ไม่เปลี่ยนเพียงเพราะวัตถุซ้อนกัน
จำสองสิ่ง ประการแรกความไม่เปลี่ยนรูปไม่ได้เป็นเวทย์มนตร์ - เป็นเพียงการขาดวิธีการกลายพันธุ์ ประการที่สองวัตถุไม่ทราบว่าตัวแปรหรือคอนเทนเนอร์อ้างอิงถึงพวกมันเพียงรู้จำนวนการอ้างอิง
หวังว่านี่จะเป็นประโยชน์กับคุณ :-)
hash()
เพราะทุกอย่างที่สืบทอดจากobject ()นั้นสามารถแฮชได้ดังนั้นคลาสย่อยจึงจำเป็นต้องปิดการแฮชอย่างชัดแจ้ง 2) Hashibility ไม่รับประกันความไม่สามารถเปลี่ยนได้ - มันง่ายที่จะทำตัวอย่างของวัตถุที่สับได้ที่ไม่แน่นอน 3) Tuples เช่นคอนเทนเนอร์ส่วนใหญ่ใน Python เพียงแค่มีการอ้างอิงไปยังวัตถุต้นแบบ - พวกเขาไม่มีหน้าที่ตรวจสอบและทำการอ้างถึงพวกมัน
นั่นเป็นเพราะสิ่งอันดับไม่มีรายการสตริงหรือตัวเลข พวกเขามีการอ้างอิงถึงวัตถุอื่น ๆ 1การไม่สามารถเปลี่ยนลำดับของการอ้างอิงที่มี tuple นั้นไม่ได้หมายความว่าคุณไม่สามารถกลายพันธุ์วัตถุที่เกี่ยวข้องกับการอ้างอิงเหล่านั้นได้ 2
1. วัตถุค่าและประเภท (ดู: สองย่อหน้าสุดท้าย)
2. ลำดับชั้นประเภทมาตรฐาน (ดู: "ลำดับไม่เปลี่ยนรูป")
ก่อนอื่นคำว่า "ไม่เปลี่ยนรูป" อาจหมายถึงสิ่งต่าง ๆ มากมายสำหรับคนที่แตกต่างกัน โดยเฉพาะอย่างยิ่งผมชอบวิธี Eric Lippert แบ่งไม่เปลี่ยนรูปในโพสต์บล็อกของเขา ที่นั่นเขาแสดงรายการประเภทไม่เปลี่ยนรูปแบบเหล่านี้:
สิ่งเหล่านี้สามารถนำมารวมกันในรูปแบบต่างๆเพื่อสร้างความเปลี่ยนแปลงไม่ได้มากขึ้นและฉันมั่นใจว่ามีอยู่จริง ชนิดที่ไม่เปลี่ยนรูปแบบที่คุณดูเหมือนจะสนใจในรูปแบบที่เปลี่ยนแปลงไม่ได้ (หรือที่รู้จักกันในชื่อสกรรมกริยา) ซึ่งวัตถุที่ไม่เปลี่ยนรูปนั้นสามารถมีวัตถุที่ไม่เปลี่ยนรูปแบบได้เท่านั้น
ประเด็นสำคัญของเรื่องนี้คือความไม่สามารถเปลี่ยนรูปลึกได้เพียงหนึ่งในหลาย ๆ รูปแบบเท่านั้น คุณสามารถยอมรับสิ่งที่คุณต้องการได้ตราบใดที่คุณทราบว่าแนวคิด "ไม่เปลี่ยนรูป" ของคุณอาจแตกต่างจากความคิดของคนอื่นในเรื่อง "ไม่เปลี่ยนรูป"
ตามที่ฉันเข้าใจแล้วคำถามนี้จำเป็นต้องถูกนำมาใช้ใหม่เป็นคำถามเกี่ยวกับการตัดสินใจในการออกแบบ: ทำไมนักออกแบบของ Python จึงเลือกที่จะสร้างประเภทลำดับที่ไม่เปลี่ยนรูปซึ่งสามารถมีวัตถุที่ไม่แน่นอนได้
เพื่อที่จะตอบคำถามนี้เราต้องคิดเกี่ยวกับวัตถุประสงค์tuplesบริการที่พวกเขาทำหน้าที่เป็นไปอย่างรวดเร็ว , วัตถุประสงค์ทั่วไปลำดับ โดยที่ในใจมันค่อนข้างชัดเจนว่าทำไม tuples จึงไม่เปลี่ยนรูป แต่สามารถมีวัตถุที่ไม่แน่นอน เพื่อปัญญา:
Tuples นั้นเร็วและมีประสิทธิภาพของหน่วยความจำ: Tuples นั้นสร้างได้เร็วกว่ารายการเพราะมันไม่เปลี่ยนรูป เปลี่ยนไม่ได้หมายความว่า tuples สามารถสร้างเป็นค่าคงที่และเต็มไปเช่นนี้โดยใช้การพับอย่างต่อเนื่อง นอกจากนี้ยังหมายความว่าพวกเขาสร้างได้เร็วขึ้นและมีหน่วยความจำที่มีประสิทธิภาพมากขึ้นเนื่องจากไม่จำเป็นต้องใช้สถานที่โดยรวม ฯลฯช้ากว่ารายการสำหรับการเข้าถึงรายการแบบสุ่ม แต่เร็วกว่าสำหรับการเปิดกล่องบรรจุ (อย่างน้อยในเครื่องของฉัน) ถ้าสิ่งอันดับเป็นสิ่งที่ไม่แน่นอนพวกเขาจะไม่เร็วสำหรับจุดประสงค์เช่นนี้
Tuples เป็นจุดประสงค์ทั่วไป : Tuples จะต้องสามารถบรรจุวัตถุชนิดใดก็ได้ พวกมันคุ้นเคยกับ (ทำอย่างรวดเร็ว) ทำสิ่งต่าง ๆ เช่นรายการอาร์กิวเมนต์ความยาวผันแปร (ผ่าน*
โอเปอเรเตอร์ในนิยามฟังก์ชัน) หากทูเปิลไม่สามารถถือวัตถุที่ไม่แน่นอนได้พวกมันคงไร้ประโยชน์สำหรับสิ่งนี้ Python จะต้องใช้รายการซึ่งอาจทำให้รายการช้าลงและจะมีประสิทธิภาพของหน่วยความจำน้อยลงอย่างแน่นอน
ดังนั้นคุณจะเห็นได้ว่าเพื่อให้บรรลุวัตถุประสงค์ของพวกเขาสิ่งอันดับจะต้องไม่เปลี่ยนรูป แต่จะต้องสามารถบรรจุวัตถุที่ไม่แน่นอนได้ หากผู้ออกแบบของ Python ต้องการสร้างวัตถุที่ไม่เปลี่ยนรูปซึ่งรับประกันได้ว่าวัตถุทั้งหมดที่มี "มี" ยังไม่เปลี่ยนรูปพวกเขาจะต้องสร้างประเภทลำดับที่สาม กำไรไม่คุ้มกับความซับซ้อนที่เพิ่มขึ้น
คุณไม่สามารถเปลี่ยนรายการid
ของมัน ดังนั้นมันจะมีรายการเดียวกันเสมอ
$ python
>>> t = (1, [2, 3])
>>> id(t[1])
12371368
>>> t[1].append(4)
>>> id(t[1])
12371368
ฉันจะไปบนกิ่งก้านที่นี่และบอกว่าส่วนที่เกี่ยวข้องที่นี่คือว่าในขณะที่คุณสามารถเปลี่ยนเนื้อหาของรายการหรือสถานะของวัตถุที่มีอยู่ภายในขอบเขตของสิ่งที่คุณไม่สามารถเปลี่ยนแปลงเป็นที่วัตถุ หรือรายการอยู่ที่นั่น หากคุณมีบางอย่างที่ขึ้นอยู่กับสิ่งที่ [3] เป็นรายการแม้ว่าจะว่างเปล่าฉันก็จะเห็นว่าสิ่งนี้มีประโยชน์
เหตุผลหนึ่งคือไม่มีวิธีทั่วไปใน Python ในการแปลงประเภทที่ไม่แน่นอนให้เป็นประเภทที่ไม่เปลี่ยนรูป (ดูPEP 351 ที่ถูกปฏิเสธและการอภิปรายที่เชื่อมโยงถึงสาเหตุที่ถูกปฏิเสธ) ดังนั้นจึงเป็นไปไม่ได้ที่จะวางวัตถุประเภทต่าง ๆ ในสิ่งอันดับถ้ามันมีข้อ จำกัด นี้รวมถึงวัตถุที่ผู้ใช้สร้างขึ้นไม่ได้
เหตุผลเดียวที่พจนานุกรมและชุดมีข้อ จำกัด นี้คือพวกเขาต้องการวัตถุที่จะแฮชเนื่องจากพวกมันถูกนำมาใช้ภายในเป็นตารางแฮช แต่โปรดสังเกตว่าพจนานุกรมแดกดันและตั้งตัวเองไม่เปลี่ยนแปลง (หรือ hashable) สิ่งอันดับไม่ใช้แฮชของวัตถุดังนั้นความไม่แน่นอนของมันจึงไม่สำคัญ
tuple นั้นไม่สามารถเปลี่ยนแปลงได้ในแง่ที่ว่า tuple นั้นไม่สามารถขยายหรือหดตัวได้ไม่ใช่ว่าสิ่งของทุกอย่างที่บรรจุอยู่นั้นจะไม่เปลี่ยนรูป มิฉะนั้นสิ่งอันดับจะน่าเบื่อ