ทำไมเราต้องใช้สิ่งอันดับใน Python (หรือชนิดข้อมูลที่ไม่เปลี่ยนรูปแบบ)


140

ฉันได้อ่านแบบฝึกหัด python หลายตัว (Dive Into Python สำหรับหนึ่ง) และการอ้างอิงภาษาบน Python.org - ฉันไม่เห็นว่าทำไมภาษาจึงต้องการสิ่งอันดับ

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

เปลี่ยนไม่ได้?

ทำไมทุกคนถึงสนใจว่าตัวแปรอาศัยอยู่ในที่ที่แตกต่างกันในความทรงจำมากกว่าตอนที่มันถูกจัดสรรไว้ในตอนแรก? ธุรกิจทั้งหมดของการเปลี่ยนแปลงไม่ได้ใน Python นี้ดูเหมือนจะเน้นมากกว่า

ใน C / C ++ ถ้าฉันจัดสรรตัวชี้และชี้ไปที่หน่วยความจำที่ใช้ได้ฉันไม่สนใจว่าที่อยู่นั้นอยู่ที่ไหนตราบใดที่มันไม่ว่างก่อนที่ฉันจะใช้

เมื่อใดก็ตามที่ฉันอ้างอิงตัวแปรนั้นฉันไม่จำเป็นต้องรู้ว่าตัวชี้ยังคงชี้ไปยังที่อยู่เดิมหรือไม่ ฉันแค่ตรวจสอบโมฆะและใช้มัน (หรือไม่)

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

>>> x='hello'
>>> id(x)
1234567
>>> x='good bye'
>>> id(x)
5432167

x ยังคงอ้างอิงข้อมูลที่ฉันต้องการทำไมทุกคนต้องสนใจว่า id ของมันเหมือนกันหรือแตกต่างกันอย่างไร


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

คำตอบ:


124
  1. วัตถุที่ไม่เปลี่ยนรูปสามารถปรับให้เหมาะสมอย่างมาก; นี่คือเหตุผลที่ว่าทำไมสตริงยังไม่เปลี่ยนรูปแบบใน Java พัฒนาค่อนข้างแยกจากกัน แต่ในเวลาเดียวกับ Python และเกือบทุกอย่างไม่เปลี่ยนแปลงในภาษาที่ใช้งานได้จริง

  2. โดยเฉพาะอย่างยิ่งในงูหลาม immutables เท่านั้นสามารถ hashable (และดังนั้นสมาชิกของชุดหรือคีย์ในพจนานุกรม) อีกครั้งการปรับให้เหมาะสมนี้ แต่มากกว่า "สำคัญ" (การออกแบบตารางแฮชที่เหมาะสมที่จัดเก็บวัตถุที่ไม่แน่นอนอย่างสมบูรณ์นั้นเป็นฝันร้าย - ไม่ว่าคุณจะทำสำเนาทุกอย่างทันทีที่คุณแฮชหรือฝันร้ายของการตรวจสอบว่า มีการเปลี่ยนแปลงนับตั้งแต่คุณได้ทำการอ้างอิงไปแล้วมันจะเป็นการย้อนกลับไปที่หัวอันน่าเกลียดของมัน)

ตัวอย่างปัญหาการเพิ่มประสิทธิภาพ:

$ python -mtimeit '["fee", "fie", "fo", "fum"]'
1000000 loops, best of 3: 0.432 usec per loop
$ python -mtimeit '("fee", "fie", "fo", "fum")'
10000000 loops, best of 3: 0.0563 usec per loop

11
@ musicfreak ดูการแก้ไขที่ฉันทำเมื่อสร้างสิ่งอันดับมากกว่า 7.6 เท่าเร็วกว่าการสร้างรายการเทียบเท่า - ตอนนี้คุณไม่สามารถพูดได้ว่าคุณ "ไม่เคยเห็นความแตกต่างที่เห็นได้ชัดเจน" อีกต่อไปเว้นแต่คุณจะนิยามคำว่า "ชัดเจน" "เป็นเรื่องที่แปลกประหลาดจริงๆ ...
Alex Martelli

11
@ musicfreak ฉันคิดว่าคุณใช้ผิดวัตถุประสงค์ "การเพิ่มประสิทธิภาพก่อนวัยอันควรเป็นรากฐานของความชั่วร้ายทั้งหมด" มีความแตกต่างอย่างมากระหว่างการเพิ่มประสิทธิภาพก่อนกำหนดในแอปพลิเคชัน (ตัวอย่างเช่นการพูดว่า "สิ่งอันดับเร็วกว่ารายการดังนั้นเราจะใช้เฉพาะสิ่งอันดับในแอปทุกตัว!") และทำการวัดประสิทธิภาพ เกณฑ์มาตรฐานของอเล็กซ์นั้นชาญฉลาดและการรู้ว่าการสร้าง tuple นั้นเร็วกว่าการสร้างรายการอาจช่วยเราในการเพิ่มประสิทธิภาพในอนาคต (เมื่อจำเป็นจริงๆ)
Virgil Dupras

5
@Alex คือ "building" tuple เร็วกว่า "สร้างรายการ" หรือเราเห็นผลลัพธ์ของ Python runtime caching tuple หรือไม่ ดูเหมือนว่าหลังสำหรับฉัน
Triptych

6
@ ACoolie ที่ถูกครอบงำโดยrandomสาย (ลองทำอย่างนั้นคุณจะเห็น!) จึงไม่สำคัญมาก ลองpython -mtimeit -s "x=23" "[x,x]"และคุณจะเห็นการเร่งความเร็วที่มีความหมายมากขึ้น 2-3 ครั้งสำหรับการสร้าง tuple กับการสร้างรายการ
Alex Martelli

9
สำหรับทุกคนที่สงสัย - เราสามารถปัดการประมวลผลข้อมูลเป็นเวลาหนึ่งชั่วโมงโดยเปลี่ยนจากรายการเป็นสิ่งอันดับ
Mark Ribau

42

ไม่มีคำตอบข้างต้นชี้ให้เห็นถึงปัญหาที่แท้จริงของรายการ tuples vs ซึ่งดูเหมือนจะไม่เข้าใจอย่างสมบูรณ์

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

["Bob", "Joe", "John", "Sam"]

เหตุผลที่มีการใช้รายการที่ถูกต้องเพราะเป็นข้อมูลประเภทที่เป็นเนื้อเดียวกันโดยเฉพาะชื่อของผู้คน แต่ทำรายการดังนี้:

["Billy", "Bob", "Joe", 42]

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

[("Billy", "Bob", "Joe", 42), ("Robert", "", "Smith", 31)]

ความผันแปรไม่ได้และความไม่แน่นอนของ Tuples และรายการไม่แตกต่างหลัก รายการคือรายการของรายการประเภทเดียวกัน: ไฟล์ชื่อวัตถุ สิ่งอันดับคือการจัดกลุ่มของวัตถุประเภทต่างๆ พวกมันมีการใช้งานที่แตกต่างกันและรายการ Python coders ที่ใช้ในทางที่ผิดสำหรับสิ่งอันดับที่มีไว้สำหรับ

โปรดอย่า


แก้ไข:

ฉันคิดว่าโพสต์บล็อกนี้อธิบายว่าทำไมฉันจึงคิดว่าดีกว่านี้: http://news.e-scribe.com/397


13
ฉันคิดว่าคุณมีวิสัยทัศน์ที่ฉันไม่เห็นด้วยอย่างน้อยก็ไม่รู้จักคนอื่น
Stefano Borini

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

14
กุยโด้สร้างประเด็นนี้เมื่อไม่กี่ปีที่ผ่านมาเช่นกัน aspn.activestate.com/ASPN/Mail/Message/python-list/1566320
John La Rooy

11
แม้ว่า Guido (ผู้ออกแบบ Python) มีจุดประสงค์เพื่อใช้เป็นรายการสำหรับข้อมูลที่เป็นเนื้อเดียวกันและสิ่งอันดับทูเปิลสำหรับต่างกันความจริงก็คือภาษาไม่ได้บังคับใช้สิ่งนี้ ดังนั้นฉันคิดว่าการตีความนี้เป็นปัญหาของสไตล์มากกว่าสิ่งอื่นใด มันจึงเกิดขึ้นว่าในกรณีการใช้งานทั่วไปของหลาย ๆ คนรายการมีแนวโน้มที่จะเป็นแบบอาเรย์ แต่สิ่งนี้ไม่ควรหยุดยั้งผู้คนไม่ให้ใช้รายการสำหรับข้อมูลที่ต่างกันถ้ามันเหมาะกับปัญหาของพวกเขาดีกว่า ในฐานะที่เป็น Zen of Python พูดว่า: การปฏิบัติจริงชนะความบริสุทธิ์
John Y

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

22

หากฉันต้องแปลง tuple เป็น set หรือ list เพื่อให้สามารถเรียงลำดับได้จุดแรกที่ใช้ tuple คืออะไร

ในกรณีนี้อาจไม่มีประเด็น นี่ไม่ใช่ปัญหาเพราะนี่ไม่ใช่หนึ่งในกรณีที่คุณควรพิจารณาใช้ tuple

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

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

โปรดทราบว่าการใช้งาน Python โดยเฉพาะอาจไม่ได้ใช้ประโยชน์จากคุณสมบัติข้างต้นทั้งหมด

คีย์พจนานุกรมต้องไม่เปลี่ยนรูปไม่เช่นนั้นการเปลี่ยนคุณสมบัติของคีย์ - ออบเจ็กต์อาจทำให้ค่าคงที่ของโครงสร้างข้อมูลไม่ถูกต้อง สิ่งอันดับสามารถใช้เป็นคีย์ได้ นี่คือผลของความถูกต้อง const

ดูเพิ่มเติม " tuples แนะนำ " จากดำน้ำลงในหลาม


2
id ((1,2,3)) == id ((1,2,3)) เป็นเท็จ คุณไม่สามารถเปรียบเทียบสิ่งอันดับได้โดยเปรียบเทียบตำแหน่งเนื่องจากไม่มีการรับประกันว่าจะถูกคัดลอกโดยการอ้างอิง
Glenn Maynard

@Glenn: โปรดสังเกตคำพูดที่เหมาะสม "เมื่อคุณใช้การคัดลอกโดยอ้างอิง" ในขณะที่ coder สามารถสร้างการใช้งานของตัวเองได้การคัดลอกโดยอ้างอิงสำหรับ tuples นั้นเป็นเรื่องสำคัญสำหรับล่าม / ผู้แปล ฉันส่วนใหญ่อ้างถึงวิธี==การใช้งานในระดับแพลตฟอร์ม
outis

1
@Glenn: (1,2,3) == (1,2,3)ยังทราบว่าการคัดลอกโดยอ้างอิงใช้ไม่ได้กับอันดับใน นั่นเป็นเรื่องของการฝึกงาน
outis

เช่นฉันกล่าวว่าค่อนข้างชัดเจนมีการรับประกันว่าพวกเขาถูกคัดลอกโดยไม่มีการอ้างอิง Tuples ไม่ได้ถูกฝึกงานใน Python นั่นเป็นแนวคิดของสตริง
Glenn Maynard

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

15

บางครั้งเราชอบใช้วัตถุเป็นกุญแจพจนานุกรม

สำหรับสิ่งที่มีค่า tuples เมื่อเร็ว ๆ นี้ (2.6+) เติบโตindex()และcount()วิธีการ


5
+1: รายการที่ไม่แน่นอน (หรือชุดที่ไม่แน่นอนหรือพจนานุกรมที่ไม่แน่นอน) เนื่องจากคีย์พจนานุกรมไม่สามารถใช้งานได้ ดังนั้นเราจึงต้องการรายการที่เปลี่ยนแปลงไม่ได้ ("tuples"), ชุดตรึงและ ... ดี ... พจนานุกรมแช่แข็งฉันคิดว่า
S.Lott

9

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

ทำไมทุกคนถึงสนใจว่าตัวแปรอาศัยอยู่ในที่ที่แตกต่างกันในความทรงจำมากกว่าตอนที่มันถูกจัดสรรไว้ในตอนแรก? ธุรกิจทั้งหมดของการเปลี่ยนแปลงไม่ได้ใน Python นี้ดูเหมือนจะเน้นมากกว่า

สิ่งเหล่านี้แตกต่างกัน ความไม่แน่นอนไม่เกี่ยวข้องกับสถานที่ที่เก็บไว้ในหน่วยความจำ มันหมายถึงสิ่งที่ชี้ไปที่ไม่สามารถเปลี่ยนแปลงได้

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

>>> x='hello'
>>> id(x)
1234567
>>> x='good bye'
>>> id(x)
5432167

สิ่งนี้ไม่ได้แก้ไข ("การกลายพันธุ์") ตัวแปร; มันกำลังสร้างตัวแปรใหม่ที่มีชื่อเดียวกันและละทิ้งตัวแปรเก่า เปรียบเทียบกับการผ่าเหล่า:

>>> a = [1,2,3]
>>> id(a)
3084599212L
>>> a[1] = 5
>>> a
[1, 5, 3]
>>> id(a)
3084599212L

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

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


>>> a = [1,2,3] >>> id (a) 3084599212L >>> a [1] = 5 >>> a [1, 5, 3] >>> id (a) 3084599212L คุณ ' เพิ่งแก้ไขประเภทข้อมูลที่ไม่แน่นอนดังนั้นจึงไม่เหมาะสมกับคำถามต้นฉบับ x = 'สวัสดี "id (x) 12345 x =" ลาก่อน "id (x) 65432 ใครจะสนใจว่ามันเป็นวัตถุใหม่หรือไม่ตราบใดที่ x ชี้ไปยังข้อมูลที่ฉันได้รับมอบหมายนั่นคือสิ่งที่สำคัญ
pyNewGuy

4
คุณสับสนเกินกว่าที่ฉันจะช่วยคุณได้
Glenn Maynard

+1 สำหรับการชี้ให้เห็นความสับสนในคำถามย่อยซึ่งดูเหมือนจะเป็นแหล่งหลักของความยากลำบากในการรับรู้คุณค่าของสิ่งอันดับ
outis

1
ถ้าเป็นไปได้ +1 อีกอันสำหรับการชี้ให้เห็นว่ารูบริกที่แท้จริงสำหรับคีย์นั้นคือวัตถุนั้น hashable หรือไม่ ( docs.python.org/glossary.html#term-hashable )
outis

7

ดังที่ gnibbler เสนอในความคิดเห็น Guido มีความเห็นที่ไม่ยอมรับ / ชื่นชมอย่างเต็มที่:“ รายการนี้มีไว้สำหรับข้อมูลที่เป็นเนื้อเดียวกันและสิ่งอันดับจะเป็นข้อมูลที่ต่างกัน” แน่นอนว่าผู้ต่อต้านหลายคนตีความสิ่งนี้ว่าเป็นความหมายว่าองค์ประกอบทั้งหมดของรายการควรเป็นประเภทเดียวกัน

ฉันชอบที่จะเห็นมันแตกต่างกันไม่เหมือนคนอื่น ๆในอดีต:

blue= 0, 0, 255
alist= ["red", "green", blue]

โปรดทราบว่าฉันถือว่าอลิสต์เป็นเนื้อเดียวกันแม้ว่าจะเป็นประเภท (alist [1])! = type (alist [2])

หากฉันสามารถเปลี่ยนลำดับขององค์ประกอบและฉันจะไม่มีปัญหาในรหัสของฉัน (นอกเหนือจากสมมติฐานเช่น "ควรจะเรียงลำดับ") จากนั้นควรใช้รายการ ถ้าไม่ใช่ (เหมือนใน tuple blueด้านบน) ดังนั้นฉันควรใช้ tuple


ถ้าฉันสามารถฉันจะโหวตคำตอบนี้ถึง 15 ครั้ง นี่คือสิ่งที่ฉันรู้สึกเกี่ยวกับสิ่งอันดับ
สิทธิ์พอล

6

พวกเขามีความสำคัญเนื่องจากพวกเขารับประกันผู้โทรว่าวัตถุที่พวกเขาผ่านจะไม่กลายพันธุ์ หากคุณทำสิ่งนี้:

a = [1,1,1]
doWork(a)

โทรมีการรับประกันของมูลค่าของไม่มีหลังจากที่โทร อย่างไรก็ตาม

a = (1,1,1)
doWorK(a)

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


1
นี่เป็นคุณสมบัติรองของ tuples มีหลายกรณีที่คุณมีวัตถุที่ไม่แน่นอนที่คุณต้องการส่งผ่านไปยังฟังก์ชั่นและไม่ได้ทำการแก้ไขไม่ว่าจะเป็นรายการที่มีอยู่ก่อนหน้าหรือคลาสอื่น ๆ ไม่มีแนวคิด "พารามิเตอร์ const โดยการอ้างอิง" ใน Python (เช่น const const foo & ใน C ++) สิ่งอันดับจะให้สิ่งนี้กับคุณถ้ามันสะดวกที่จะใช้ tuple เลย แต่ถ้าคุณได้รับรายการจากผู้โทรคุณจะแปลงมันเป็น tuple ก่อนที่จะส่งไปที่อื่นหรือไม่?
Glenn Maynard

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

a = [1,1,1] doWork (a) ถ้า dowork () ถูกกำหนดเป็น def dowork (arg): arg = [0,0,0] การเรียก dowork () ในรายการหรือ tuple มีผลลัพธ์เดียวกัน
pyNewGuy


1

คำถามของคุณ (และความคิดเห็นติดตาม) มุ่งเน้นไปที่ id () เปลี่ยนแปลงในระหว่างการมอบหมาย การมุ่งเน้นที่ผลที่ตามมาของความแตกต่างระหว่างการแทนที่วัตถุที่ไม่เปลี่ยนรูปและการปรับเปลี่ยนวัตถุที่ไม่แน่นอนแทนที่จะเป็นความแตกต่างนั้นอาจไม่ใช่วิธีที่ดีที่สุด

ก่อนที่เราจะดำเนินการตรวจสอบให้แน่ใจว่าพฤติกรรมที่แสดงด้านล่างนี้เป็นสิ่งที่คุณคาดหวังจาก Python

>>> a1 = [1]
>>> a2 = a1
>>> print a2[0]
1
>>> a1[0] = 2
>>> print a2[0]
2

ในกรณีนี้เนื้อหาของ a2 มีการเปลี่ยนแปลงแม้ว่าจะมีเพียง a1 เท่านั้นที่มีการกำหนดค่าใหม่ ตรงกันข้ามกับสิ่งต่อไปนี้:

>>> a1 = (1,)
>>> a2 = a1
>>> print a2[0]
1
>>> a1 = (2,)
>>> print a2[0]
1

ในกรณีหลังนี้เราแทนที่รายการทั้งหมดแทนที่จะอัปเดตเนื้อหา ด้วยประเภทที่ไม่เปลี่ยนรูปแบบเช่นสิ่งอันดับนี่เป็นพฤติกรรมเดียวที่อนุญาต

เหตุใดเรื่องนี้ สมมติว่าคุณมีพจน์:

>>> t1 = (1,2)
>>> d1 = { t1 : 'three' }
>>> print d1
{(1,2): 'three'}
>>> t1[0] = 0  ## results in a TypeError, as tuples cannot be modified
>>> t1 = (2,3) ## creates a new tuple, does not modify the old one
>>> print d1   ## as seen here, the dict is still intact
{(1,2): 'three'}

การใช้ tuple ทำให้พจนานุกรมปลอดภัยจากการเปลี่ยนคีย์ "ออกจากใต้" เป็นรายการที่แฮชเป็นค่าอื่น นี่เป็นสิ่งสำคัญที่จะช่วยให้การใช้งานมีประสิทธิภาพ


ในขณะที่คนอื่น ๆ ชี้ให้เห็นความไม่เปลี่ยนแปลง! = hashability tuples ทั้งหมดไม่สามารถใช้เป็นคีย์พจนานุกรม: {([1], [2]): 'value'} ล้มเหลวเนื่องจากรายการที่ไม่แน่นอนใน tuple สามารถเปลี่ยนแปลงได้ แต่ {((1), (2)): ' ค่า '} ก็โอเค
Ned Deily

เน็ดมันเป็นเรื่องจริง แต่ฉันไม่แน่ใจว่าความแตกต่างนั้นเป็นสิ่งที่ตอบคำถามที่ถูกถาม
Charles Duffy

@ K.Nicholas การแก้ไขที่คุณอนุมัติที่นี่ได้เปลี่ยนรหัสในลักษณะที่จะกำหนดจำนวนเต็มไม่ใช่ tuple เลยทำให้การดำเนินการดัชนีในภายหลังล้มเหลวจึงไม่สามารถทดสอบได้ว่าใหม่ การถอดเสียงเป็นไปได้จริง ปัญหาที่ระบุไว้ถูกต้องแน่นอน; ทางออกที่ไม่ถูกต้อง
Charles Duffy

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