Чи гарантовано список Python, щоб його елементи залишалися в тому порядку, в який вони вставлені?


318

Якщо у мене є наступний код Python

>>> x = []
>>> x = x + [1]
>>> x = x + [2]
>>> x = x + [3]
>>> x
[1, 2, 3]

Чи xгарантовано завжди буде [1,2,3], чи можливі інші впорядкування проміжних елементів?

Відповіді:


479

Так, порядок елементів у списку python зберігається.


17
Це правильна відповідь, тому я не хочу додавати іншу. Він також міг використати list.append, щоб дійсно розслабити розум. docs.python.org/2/tutorial/datastructures.html
NG.

1
що робити, якщо я повертаю локальний список з функції та використовую його у викликовій функції. Тобто def fn_1(): lst = [] lst.append(1) lst.append(2) return lstі def fn_2(): print(fn_1())чи буде замовлення завжди однаковим незалежно від того, скільки разів або де я колись використовувати fn_1 ()?
TheCuriousOne

6
Так, порядок елементів у списку python зберігається. ;)
sge

82

Словом, так, порядок зберігається. Довго:

Загалом наступні визначення завжди застосовуватимуться до об'єктів, таких як списки:

Список являє собою набір елементів , які можуть містити елементи, що повторюються і мають певний порядок, як правило , не змінюється , якщо явно не зроблено , щоб зробити це. стеки та черги - це обидва типи списків, які забезпечують специфічну (часто обмежену) поведінку для додавання та видалення елементів (стеки є LIFO, черги - FIFO). Списки - це практичні уявлення про списки речей. Рядок можна розглядати як список символів, оскільки порядок важливий ( "abc" != "bca"), а дублікати у вмісті рядка безумовно дозволені ( "aaa"можуть існувати і != "a").

Набір являє собою сукупність елементів , які не можуть містити дублікати і має не визначений порядок , який може або не може змінюватися з плином часу. Набори не представляють списків речей настільки, як вони описують масштаби певного вибору речей. Внутрішня структура набору, як його елементи зберігаються відносно один одного, зазвичай не мають на меті передачі корисної інформації. У деяких реалізаціях набори завжди внутрішньо сортуються; в інших замовлення просто не визначене (зазвичай це залежить від хеш-функції).

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

Ця схема іменування справедлива для всіх мов програмування, які я знаю, включаючи Python, C ++, Java, C # та Lisp (в яких списки, що не дотримуються порядку, були б особливо катастрофічними). Якщо хтось знає, що це не так, будь ласка, скажіть так, і я відредагую свою відповідь. Зауважте, що конкретні реалізації можуть використовувати інші назви для цих об'єктів, такі як вектор у C ++ та flex у ALGOL 68 (обидва списки; flex технічно є лише масивом, який може бути повторно встановлений).

Якщо у вашому випадку залишилася якась плутанина через специфіку того, як +працює тут знак, просто знайте, що порядок важливий для списків, і якщо немає дуже вагомих причин вважати, що в іншому випадку ви можете майже завжди впевнено припускати, що операції зі списком зберігають порядок . У цьому випадку +знак поводиться так само, як і для рядків (які так чи інакше є лише списками символів): він бере зміст списку і розміщує його за змістом іншого.

Якщо у нас є

list1 = [0, 1, 2, 3, 4]
list2 = [5, 6, 7, 8, 9]

Тоді

list1 + list2

Це те саме, що

[0, 1, 2, 3, 4] + [5, 6, 7, 8, 9]

Який оцінює

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Так само як

"abdcde" + "fghijk"

Виробляє

"abdcdefghijk"

1
Я десь прочитав, що оскільки специфікація масиву JSON не визначає, що масиви підтримують операції з масивом порядку, не гарантується підтримка порядку. Я не можу знайти джерело для цього. І основна структура масиву - це все ще особливий випадок об'єкта з нумерованими індексами, тож це не суперечить вашому твердженню, просто цікавий примх, я думав.
Multihunter

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

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

5

Ви плутаєте "набори" та "списки". Набір не гарантує замовлення, але списки це роблять.

Набори оголошуються з допомогою фігурних дужок: {}. На відміну від цього , списки оголошуються з допомогою квадратних дужок: [].

mySet = {a, b, c, c}

Не гарантує замовлення, але список:

myList = [a, b, c]

1
Зауважте, що набір також гарантує не дублювання. Список може мати повторювані елементи, а набір - не.
Натаніел Форд

4

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

Однак не все в Python незмінне. Наприклад, списки змінюються --- вони можуть змінюватися після створення. Так, наприклад, якщо у вас був список списків

>>> a = [[1], [2], [3]]
>>> a[0].append(7)
>>> a
[[1, 7], [2], [3]]

Тут я змінив перший запис a(додав 7до нього). Можна уявити перемішування речей і отримання тут несподіваних речей, якщо ви не обережні (і справді, це трапляється з усіма, коли вони так чи інакше починають програмувати в Python; просто шукайте цей сайт для "зміни списку під час циклу" це ", щоб побачити десятки прикладів).

Також варто відзначити, що x = x + [a]і x.append(a)це не те ж саме. Другий мутує x, а перший створює новий список і призначає його x. Щоб побачити різницю, спробуйте встановити, y = xперш ніж додавати що-небудь xі намагатися кожен, і подивіться на різницю, яку вони мають зробити y.


0

aList = [1,2,3]

i = 0

for item in aList:  

    if i<2:  

            aList.remove(item)  

    i+=1  

список

[2]

Мораль полягає в тому, що при зміні списку в циклі, керованому списком, робиться два кроки:

aList=[1,2,3]
i=0
for item in aList:
    if i<2:
        aList[i]="del"
    i+=1

aList

['del', 'del', 3]
for i in range(2):
    del aList[0]

aList
[3]

0

Так, списки та кортежі завжди упорядковуються, а словники - ні


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