Список Python vs. Array - коли використовувати?


374

Якщо ви створюєте 1d масив, ви можете реалізувати його як список, або ж використовувати модуль 'масив' у стандартній бібліотеці. Я завжди використовував списки для 1d масивів.

Яка причина чи обставина, коли я хотів би замість цього використовувати модуль масиву?

Це для оптимізації продуктивності та пам’яті чи я пропускаю щось очевидне?

Відповіді:


438

По суті, списки Python дуже гнучкі і можуть містити абсолютно неоднорідні, довільні дані, і їх можна додавати дуже ефективно, за амортизованим постійним часом . Якщо вам потрібно скоротити та розробити свій список вчасно та без зайвих клопотів, це шлях. Але вони використовують набагато більше простору , ніж масиви C .

З array.arrayіншого боку, тип - це лише тонка обгортка на масивах C. Він може вміщувати лише однорідні дані, всі одного типу, і тому він використовує лише sizeof(one object) * lengthбайти пам'яті. Здебільшого, ви повинні використовувати його, коли вам потрібно піднести масив C до розширення або системного виклику (наприклад, ioctlабо fctnl).

array.arrayце також розумний спосіб представити змінну рядок в Python 2.x ( array('B', bytes)). Однак Python 2.6+ та 3.x пропонує змінений рядок байтів як bytearray.

Однак якщо ви хочете займатися математикою на однорідному масиві числових даних, то вам набагато краще використовувати NumPy, який може автоматично векторизувати операції над складними багатовимірними масивами.

Щоб зробити короткий короткийarray.array опис : корисно, коли вам потрібен однорідний масив C з інших причин, ніж математика .


9
Чи має numpy.ndarray такий самий слід пам'яті, як array.array?
Гордон Бін

6
@ Gordon, він повинен бути дуже схожим у випадку з великим суміжним масивом: їм обом буде потрібно sizeof(element)× (кількість елементів) байтів, а також невеликий фіксований заголовок для накладних витрат. Однак у ndarray є кілька вдосконалених варіантів роботи з неспорідненими та розрідженими масивами, і я думаю, що деякі підключаються стратегії розподілу пам’яті для великих масивів… деякі з цих додаткових функцій зроблять її користувачем менше пам’яті, а інші покращать продуктивність, використовуючи більше пам'ять.
Дан Ленськи

Також корисно, коли пам'ять є такою проблемою, як програмування мікроконтролерів з мікропітоном
janscas

Можна шукати i-й елемент масиву в постійний час, тоді як у пов'язаному списку він приймає порядок 'n' в гіршому випадку. Який час пошуку i-го елемента в списку python?
Нітхійський натовп щастя

7
@NithishInpursuitOfhappiness, список Python - це не пов'язаний список. Він представлений внутрішньо як масив і має ті ж характеристики складності в часі, що і Java ArrayList. Таким чином, отримання та встановлення i-го елемента списку Python вимагає постійного часу . Додавання елемента до списку Python потребує постійного амортизованого часу, оскільки розмір масиву збільшується вдвічі, коли йому не вистачає місця. Вставлення елемента в середину списку Python або видалення його займає O (n) час, оскільки елементи потрібно змістити. Для ознайомлення дивіться: wiki.python.org/moin/TimeComplexity
geofflee

66

Майже для всіх випадків нормальний список - це правильний вибір. Модуль масивів більше схожий на тонку обгортку над масивами С, яка дає вам набір сильно набраних контейнерів (див. Документи ), з доступом до таких типів типу C, як короткі чи подвійні підписи / неподписані, які не є частиною вбудованої -в типах. Я б сказав, що використовуйте модуль масивів, тільки якщо він вам справді потрібен, у всіх інших випадках дотримуйтесь списків.


3
Можливо, ніколи його не використовували по-справжньому, але було б цікаво запустити деякі мікро-орієнтири.
Андре

13
Насправді я зробив швидкий тест - я приуротив підсумовування списку зі записами 100M та таким же тестом із відповідним масивом, і список насправді був приблизно на 10% швидшим.
Mo

38
Списки швидші, тому що операції над "необробленими" даними масиву потребують постійного створення та знищення об'єктів python під час читання з масиву чи запису до нього.
tzot

7
@Moe, як я зазначав у моїй обороні вище, Python вбудований arrayв не призначений для виконання математика . Якщо ви спробуєте NumPy's ndarrayдля підбиття масиву з 10 ^ 8 чисел, він повністю вибухне list. @tzot має правильне уявлення про те, чому вбудований у arrayматематику повільний.
Дан Ленскі

2
Я щойно тестував це, numpy на 86.6x швидше на моїй машині.
Марк

53

Модуль масиву - це одна з тих речей, у яких, мабуть, не виникає необхідності, якщо ви не знаєте, чому б ви його використовували (і врахуйте, що я не намагаюся сказати це поблажливо!) . Більшу частину часу модуль масиву використовується для взаємодії з кодом С. Щоб дати вам більш пряму відповідь на запитання щодо продуктивності:

Масиви ефективніші, ніж списки для деяких застосувань. Якщо вам потрібно виділити масив, який ви ЗНАЄте, він не зміниться, то масиви можуть бути швидшими та використовувати менше пам'яті. GvR має анекдот оптимізації, в якому модуль масиву виходить переможцем (довго читати, але варто).

З іншого боку, частина причини, по якій списки споживають більше пам’яті, ніж масиви, полягає в тому, що python виділить кілька додаткових елементів, коли всі виділені елементи звикнуть. Це означає, що додавання елементів до списків відбувається швидше. Тож якщо ви плануєте додавати елементи, шлях - це список.

TL; DR Я б використовував масив тільки в тому випадку, якщо у вас виникли виняткові потреби в оптимізації або вам потрібно взаємодіяти з кодом C (і не можете використовувати pyrex ).


1
+1 для конкретного прикладу та згадування переваги швидкості. Верхня відповідь змусила мене замислитись: "Чи можливий компроміс у пам'яті часу?" і "Чи є для цього користь, що не дуже езотеричний випадок із низькою пам'яттю?"
leewz

@leewz точно, це слід розглядати як відповідь.
Гаурі Шанкар Бадола

21

Це торгівля!

плюси кожного:

список

  • гнучка
  • можуть бути неоднорідними

масив (наприклад: numpy масив)

  • масив рівномірних значень
  • однорідний
  • компактний (за розміром)
  • ефективний (функціональність та швидкість)
  • зручно

2
питання стосується модуля масиву в python; не нумеровані масиви. Немає плюсів, крім ефективності розміру. Вони не швидші.
NONONONONO

14

Я розумію, що масиви зберігаються ефективніше (тобто як суміжні блоки пам'яті проти покажчиків на об’єкти Python), але я не знаю жодної користі від продуктивності. Крім того, з масивами ви повинні зберігати примітиви одного типу, тоді як списки можуть зберігати все, що завгодно.


8

Стандартні масиви бібліотеки корисні для двійкових вводу / виводу, таких як переклад списку входів у рядок для запису, скажімо, у хвильовий файл. Це говорило, як багато хто вже відзначав, якщо ви збираєтеся робити якусь реальну роботу, то вам слід розглянути можливість використання NumPy.


6

Якщо ви збираєтесь використовувати масиви, розгляньте пакети numpy або scipy, які дають вам масиви з набагато більшою гнучкістю.


5

Масив можна використовувати лише для конкретних типів, тоді як списки можуть використовуватися для будь-якого об'єкта.

Масиви можуть також містити лише дані одного типу, тоді як у списку можуть бути записи різних типів об'єктів.

Масиви також ефективніші для деяких чисельних обчислень.


4
Вбудовані масиви пітона не ефективні, а лише пам'ять.
tzot

Є такі випадки, коли масиви є більш ефективними в плані обробки. Дивіться мою публікацію нижче: stackoverflow.com/questions/176011/…
Джейсон Бейкер

0

Важливою відмінністю між numpy масивом та списком є ​​те, що фрагменти масиву - це види на вихідний масив. Це означає, що дані не копіюються, і будь-які модифікації представлення відображатимуться у вихідному масиві.


0

Ця відповідь підсумовує майже всі запити щодо використання списку та масиву:

  1. Основна відмінність цих двох типів даних - це операції, які ви можете виконувати над ними. Наприклад, ви можете розділити масив на 3, і він розділить кожен елемент масиву на 3. Те ж не можна зробити зі списком.

  2. Список є частиною синтаксису python, тому його не потрібно декларувати, тоді як вам потрібно оголосити масив перед його використанням.

  3. Ви можете зберігати значення різних типів даних у списку (неоднорідних), тоді як у масиві ви можете зберігати значення лише одного типу даних (однорідних).

  4. Масиви, багаті функціональними можливостями і швидкодіючі, широко використовуються для арифметичних операцій та для зберігання великої кількості даних - порівняно зі списком.

  5. Масиви займають менше пам'яті порівняно зі списками.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.