Python List vs. Array - เมื่อใดควรใช้?


374

หากคุณกำลังสร้างอาร์เรย์ 1d คุณสามารถใช้มันเป็นรายการหรือใช้โมดูล 'อาร์เรย์' ในไลบรารีมาตรฐาน ฉันใช้รายการสำหรับอาร์เรย์ 1 วันเสมอ

อะไรคือเหตุผลหรือสถานการณ์ที่ฉันต้องการใช้โมดูลอาร์เรย์แทน

สำหรับประสิทธิภาพและการเพิ่มประสิทธิภาพหน่วยความจำหรือฉันขาดสิ่งที่ชัดเจน?

คำตอบ:


438

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

array.arrayชนิดในมืออื่น ๆ เป็นเพียงเสื้อคลุมบาง ๆ บนอาร์เรย์ C มันสามารถเก็บข้อมูลที่เป็นเนื้อเดียวกันเท่านั้นทุกประเภทเดียวกันและดังนั้นจึงใช้sizeof(one object) * lengthหน่วยความจำไบต์เท่านั้น ส่วนใหญ่คุณควรใช้เมื่อคุณต้องการเปิดเผยอาร์เรย์ C ให้กับส่วนขยายหรือการเรียกของระบบ (ตัวอย่างเช่นioctlหรือfctnl)

array.arrayเป็นวิธีที่สมเหตุสมผลในการแสดงสตริงที่ไม่แน่นอนใน Python 2.x ( array('B', bytes)) แต่งูหลาม 2.6+ และ 3.x ข้อเสนอที่ไม่แน่นอนไบต์bytearrayสตริง

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

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


9
numpy.ndarray มี footprint หน่วยความจำเหมือนกับ array.array หรือไม่
Gordon Bean

6
@ กอร์ดอนมันควรจะคล้ายกันมากในกรณีของอาเรย์ขนาดใหญ่ที่ต่อเนื่องกัน: ทั้งคู่จะต้องใช้sizeof(element)× (จำนวนองค์ประกอบ) ไบต์พร้อมกับส่วนหัวคงที่ขนาดเล็กสำหรับค่าใช้จ่าย อย่างไรก็ตาม ndarray มีตัวเลือกขั้นสูงบางอย่างสำหรับการรับมือกับอาร์เรย์ discontiguous และเบาบางและฉันคิดว่ากลยุทธ์ pluggable บางอย่างสำหรับการจัดสรรหน่วยความจำสำหรับอาร์เรย์ขนาดใหญ่ ... บางส่วนของคุณสมบัติขั้นสูงเหล่านี้จะทำให้ผู้ใช้น้อยลงหน่วยความจำขณะที่คนอื่นจะช่วยเพิ่มประสิทธิภาพโดยใช้มากขึ้นหน่วยความจำ
Dan Lenski

ยังมีประโยชน์เมื่อหน่วยความจำที่เป็นปัญหาเช่นเมื่อเขียนโปรแกรมไมโครคอนโทรลเลอร์กับ micropython
janscas

หนึ่งสามารถค้นหาองค์ประกอบของอาร์เรย์ในเวลาคงที่ในขณะที่รายการที่เชื่อมโยงจะใช้คำสั่ง 'n' ในกรณีที่เลวร้ายที่สุด เวลาค้นหาองค์ประกอบ i'th ในรายการหลามคืออะไร
Nithish Inpursuit Ofhappiness

7
@NithishInpursuitOfhappiness รายการ Python ไม่ใช่รายการที่เชื่อมโยง มันเป็นตัวแทนของภายในเป็นอาร์เรย์และมีลักษณะความซับซ้อนเวลาเดียวกันกับ Java ArrayList ดังนั้นการได้รับและการตั้งค่าองค์ประกอบ i'th ของรายการงูใหญ่ต้องใช้เวลาอย่างต่อเนื่อง การผนวกองค์ประกอบเข้ากับรายการ Python ใช้เวลาคงที่ตัดจำหน่ายเนื่องจากขนาดอาร์เรย์เป็นสองเท่าเมื่อหมดพื้นที่ การแทรกองค์ประกอบเข้าหรือออกจากกลางรายการ Python ใช้เวลาO (n)เพราะต้องเปลี่ยนองค์ประกอบ สำหรับการอ้างอิงโปรดดู: wiki.python.org/moin/TimeComplexity
geofflee

66

เกือบทุกกรณีรายการปกติเป็นตัวเลือกที่เหมาะสม โมดูลอาร์เรย์เป็นเหมือน wrapper ที่บางกว่า C arrays ซึ่งให้ชนิดของคอนเทนเนอร์ที่พิมพ์ได้ดี (ดูเอกสาร ) ที่มีการเข้าถึงประเภท C-like มากขึ้นเช่นสั้น / ลงนามหรือไม่ได้ลงนามซึ่งไม่ได้เป็นส่วนหนึ่งของการสร้าง - ในประเภท ฉันว่าใช้โมดูลอาร์เรย์เฉพาะในกรณีที่คุณต้องการจริงๆในกรณีอื่น ๆ ทั้งหมดติดกับรายการ


3
เป็นไปได้ไม่เคยใช้จริง ๆ แต่จะน่าสนใจในการเรียกใช้เกณฑ์มาตรฐานขนาดเล็ก
André

13
ที่จริงแล้วฉันทำการทดสอบอย่างรวดเร็ว - ฉันหมดเวลารวมรายการที่มีรายการ 100M และการทดสอบเดียวกันกับอาร์เรย์ที่เกี่ยวข้องและรายการนั้นเร็วขึ้นประมาณ 10%
Moe

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

7
@Moe ที่ผมชี้ให้เห็นในคำตอบของฉันข้างต้น ธ ในตัวarrayจะไม่ได้หมายสำหรับทำคณิตศาสตร์ หากคุณลองใช้ NumPy ndarrayเพื่อหาจำนวนรวมของตัวเลข 10 ^ 8 มันจะlistหายไปอย่างสมบูรณ์ @tzot มีความคิดที่ถูกต้องเกี่ยวกับสาเหตุที่ทำให้ตัวบิวด์อินarrayช้าสำหรับคณิตศาสตร์
Dan Lenski

2
ฉันเพิ่งทดสอบมันเร็วกว่าเครื่องของฉันอีก 86.6x
ทำเครื่องหมาย

53

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

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

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

TL; DR ฉันจะใช้อาร์เรย์เฉพาะเมื่อคุณมีความต้องการเพิ่มประสิทธิภาพที่ยอดเยี่ยมหรือคุณต้องการเชื่อมต่อกับรหัส C (และไม่สามารถใช้pyrex )


1
+1 สำหรับตัวอย่างที่เป็นรูปธรรมและกล่าวถึงประโยชน์ของความเร็ว คำตอบอันดับต้นทำให้ฉันสงสัยว่า "มีการแลกเปลี่ยนเวลาความจำหรือไม่?" และ "มีประโยชน์อะไรกับกรณีนี้ใช่หรือไม่ที่เป็นกรณีความจำน้อยลึกลับ?"
leewz

@ leewz ตรงนี้ควรถือเป็นคำตอบ
Gauri Shankar Badola

21

มันเป็นการแลกเปลี่ยน!

ข้อดีของแต่ละคน:

รายการ

  • คล่องตัว
  • สามารถแตกต่างกันได้

อาร์เรย์ (เช่น: อาร์เรย์ที่ไม่ระบุ)

  • อาร์เรย์ของค่าสม่ำเสมอ
  • เหมือนกัน
  • กะทัดรัด (ขนาด)
  • มีประสิทธิภาพ (ฟังก์ชั่นและความเร็ว)
  • สะดวกสบาย

2
คำถามคือการอ้างอิงถึงโมดูลอาร์เรย์ในหลาม; ไม่ใช่อาร์เรย์ numpy พวกเขาไม่มีข้อดีมากมายยกเว้นประสิทธิภาพของขนาด พวกเขาไม่ได้เร็วขึ้น
NONONONONO

14

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


8

อาร์เรย์ไลบรารีมาตรฐานมีประโยชน์สำหรับไบนารี I / O เช่นการแปลรายการของ ints เป็นสตริงที่จะเขียนพูดไฟล์ wave ที่กล่าวไว้ดังที่หลายคนกล่าวไว้แล้วหากคุณจะทำงานจริงใด ๆ คุณควรพิจารณาใช้ NumPy



5

Array สามารถใช้ได้กับบางประเภทเท่านั้นในขณะที่รายการสามารถใช้กับวัตถุใด ๆ ก็ได้

อาร์เรย์สามารถมีเพียงข้อมูลประเภทเดียวในขณะที่รายการสามารถมีรายการประเภทวัตถุต่าง ๆ ได้

อาร์เรย์ยังมีประสิทธิภาพมากกว่าสำหรับการคำนวณเชิงตัวเลข


4
ชุดงูหลามในตัวไม่ได้มีประสิทธิภาพที่ชาญฉลาด แต่มีประสิทธิภาพสำหรับหน่วยความจำเท่านั้น
tzot

มีหลายกรณีที่อาร์เรย์มีประสิทธิภาพมากกว่าในแง่ของการประมวลผล ดูโพสต์ของฉันด้านล่าง: stackoverflow.com/questions/176011/…
Jason Baker

0

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


0

คำตอบนี้จะสรุปคำถามเกือบทั้งหมดเกี่ยวกับเวลาที่จะใช้ List and Array:

  1. ความแตกต่างที่สำคัญระหว่างสองประเภทข้อมูลคือการดำเนินการที่คุณสามารถทำได้ ตัวอย่างเช่นคุณสามารถหารอาร์เรย์ด้วย 3 และมันจะแบ่งแต่ละองค์ประกอบของอาร์เรย์ด้วย 3 เหมือนกันไม่สามารถทำได้กับรายการ

  2. รายการเป็นส่วนหนึ่งของไวยากรณ์ของงูใหญ่ดังนั้นจึงไม่จำเป็นต้องประกาศในขณะที่คุณต้องประกาศอาร์เรย์ก่อนที่จะใช้

  3. คุณสามารถเก็บค่าของชนิดข้อมูลที่แตกต่างกันในรายการ (ต่างกัน) ในขณะที่ใน Array คุณสามารถจัดเก็บค่าของชนิดข้อมูลเดียวกันเท่านั้น (เป็นเนื้อเดียวกัน)

  4. อาร์เรย์มีฟังก์ชันการทำงานที่หลากหลายและรวดเร็วมีการใช้กันอย่างแพร่หลายสำหรับการดำเนินการทางคณิตศาสตร์และสำหรับการจัดเก็บข้อมูลจำนวนมาก - เปรียบเทียบกับรายการ

  5. อาร์เรย์ใช้หน่วยความจำน้อยกว่าเมื่อเทียบกับรายการต่างๆ

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