Почему этот итеративный код, расширяющий список, дает IndexError: индекс назначения списка вне диапазона?

194

Пожалуйста, рассмотрите следующий код:

i = [1, 2, 3, 5, 8, 13]
j = []
k = 0

for l in i:
    j[k] = l
    k += 1

print j

Вывод (Python 2.6.6 на Win 7 32-разрядная версия):

> Traceback (most recent call last): 
>     j[k] = l IndexError: list assignment index out of range

Я думаю, это что-то простое, я не понимаю. Может кто-нибудь прояснить это?

Vladan
источник
7
appendэто правильное решение для вашего случая использования, однако в списке Python есть метод вставки, который можно вставить непосредственно в i-ую позицию в списке. j.insert(k, l)
opensourcegeek
Могу я спросить, почему не работает решение ОП? Зачем использовать приложение?
Хелен

Ответы:

318

jпустой список, но вы пытаетесь записать элемент [0]в первой итерации, которой еще нет.

Вместо этого попробуйте следующее, чтобы добавить новый элемент в конец списка:

for l in i:
    j.append(l)

Конечно, вы никогда бы не сделали это на практике, если бы все, что вы хотели сделать, это скопировать существующий список. Вы бы просто сделали:

j = list(i)

В качестве альтернативы, если вы хотите использовать список Python как массив в других языках, вы можете предварительно создать список с его элементами, для которых установлено нулевое значение ( Noneв приведенном ниже примере), а затем перезаписать значения в определенных позициях:

i = [1, 2, 3, 5, 8, 13]
j = [None] * len(i)
#j == [None, None, None, None, None, None]
k = 0

for l in i:
   j[k] = l
   k += 1

Необходимо понимать, что listобъект не позволит вам присвоить значение отсутствующему индексу.

Стив Мейн
источник
2
Хорошо, большое спасибо. Я не знал, какой из них похвалить, поскольку есть три почти одинаковых ответа. Это наиболее описательный, я думаю. Приветствия
Владан
Я вижу, что это может сбивать с толку тех, кто приходит из других языков, таких как PHP или C. j - это тип списка, а не массива. С типом списка, я не думаю, что это подписка. Очень сбивает с толку, если приходят с других языков.
Нгуай Аль
@Nguaial Тип списка является подписанным, но вы можете получить доступ только к уже существующим элементам - вы не можете создать элемент, пытаясь выполнить запись в индекс, который находится вне диапазона. j [0] = "foo" будет работать, если в списке уже есть хотя бы один элемент.
Стив Мейн
52

Другой вариант - инициализировать j:

j = [None] * len(i)
Rsh
источник
3
Вы хотите использовать len (i) вместо max.
Стив Мейн
25

Делай j.append(l)вместо j[k] = lи kвообще избегай.

Хачик
источник
2
Более короткий (более питонский?) Путь может бытьj+=[l]
Олег Припин
2
@BlaXpirit: Думаю, это станет бременем для сборщика мусора.
Хачик
2
@BalXpirit: Учитывая, что это сохраняет только несколько символов (особенно потому, что вам нужно добавить пробелы, чтобы это было приемлемо), и это .appendгораздо более распространено (возможно, по причине - я думаю, что это немного легче понять), не очень хорошо в любом случае. (Изменить @khachik: Нет, +=изменяет на месте)
15

Вы также можете использовать понимание списка:

j = [l for l in i]

или сделайте копию этого, используя утверждение:

j = i[:]
Джейсон Сундрам
источник
эта вторая конструкция аккуратна
Джавадба
2
Если единственная цель состоит в том, чтобы скопировать список, вы можете просто сказать, что j = list (i) Я думаю, что вопрос больше в поведении списков, а не в том, чтобы конкретно нуждаться в способе копирования элементов.
Стив Мейн
10
j.append(l)

Также избегайте использования строчных букв "L", потому что их легко спутать с 1

Том
источник
7

Я думаю, что вставка метода Python - это то, что вы ищете:

Вставляет элемент x в положение i. list.insert (я, х)

array = [1,2,3,4,5]

array.insert(1,20)

print(array)

# prints [1,2,20,3,4,5]
Мехмет Каган Каялп
источник
1
Нет смысла использовать, insertкогда appendбыл предоставлен специально для этой цели.
Holdenweb
На момент информации, код на самом деле принты [1, 20, 2, 3, 4, 5].
Holdenweb
Вы вставили в индекс 1, смещая индексы 1 и далее. Вставленное значение не заканчивается индексом 2. Iist.insert () действительно нужен только тогда, когда вы не хотите добавлять элемент в конец списка; вопрос здесь делает именно это, поэтому list.append () предпочтительнее.
Мартин Питерс
На самом деле, почему я так отвечаю на этот вопрос, я тоже удивлен: D Не знаю, что я думал :) Это именно "list.append ()", который является принятым ответом. Я думаю, что это помогает людям или дает идею для решения их проблем, чтобы получить 5 хитов.
Мехмет Каган
5

Вы можете использовать словарь (аналог ассоциативного массива) для j

i = [1, 2, 3, 5, 8, 13]
j = {} #initiate as dictionary
k = 0

for l in i:
    j[k] = l
    k += 1

print j

напечатает:

{0: 1, 1: 2, 2: 3, 3: 5, 4: 8, 5: 13}
Седрик
источник
Для последовательных указателей, начинающихся с 0, сопоставление обычно является неправильной структурой данных, особенно когда сопоставления не имеют срезов или реверсирования, поскольку они не предназначены для передачи какого-либо конкретного порядка.
Мартин Питерс
2

Еще один способ:

j=i[0]
for k in range(1,len(i)):
    j = numpy.vstack([j,i[k]])

В этом случае jбудет массив NumPy

Alex
источник
0

Может быть, вам нужно расширить ()

i=[1,3,5,7]
j=[]
j.extend(i)
Фред Му
источник