Dlaczego ten iteracyjny kod zwiększający listę powoduje, że IndexError: indeks przypisania listy jest poza zakresem?


194

Proszę wziąć pod uwagę następujący kod:

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

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

print j

Dane wyjściowe (Python 2.6.6 w Win 7 32-bit) to:

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

Myślę, że to coś prostego, czego nie rozumiem. Czy ktoś może to wyjaśnić?


6
appendjest właściwym rozwiązaniem dla twojego przypadku użycia, jednak istnieje metoda wstawiania na liście python, która może wstawiać bezpośrednio do i-tej pozycji na liście. j.insert(k, l)
opensourcegeek

Czy mogę zapytać, dlaczego rozwiązanie OP nie zadziałałoby? Dlaczego warto korzystać z append?
Helen

Odpowiedzi:


317

jjest pustą listą, ale próbujesz napisać do elementu [0]w pierwszej iteracji, która jeszcze nie istnieje.

Zamiast tego spróbuj wykonać następujące czynności, aby dodać nowy element na końcu listy:

for l in i:
    j.append(l)

Oczywiście nigdy nie zrobiłbyś tego w praktyce, gdyby wszystko, co chciałeś zrobić, to skopiować istniejącą listę. Po prostu zrobiłbyś:

j = list(i)

Alternatywnie, jeśli chcesz używać listy Python jako tablicy w innych językach, możesz wstępnie utworzyć listę z jej elementami ustawionymi na wartość zerową ( Nonew poniższym przykładzie), a później zastąpić wartości w określonych pozycjach:

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

Należy zdać sobie sprawę, że listobiekt nie pozwoli ci przypisać wartości do indeksu, który nie istnieje.


2
Ok, bardzo dziękuję. Nie wiedziałem, którą pochwalić, ponieważ istnieją trzy prawie takie same odpowiedzi. Myślę, że jest to najbardziej opisowe. Na zdrowie
Vladan,

Widzę, że może to być bardzo mylące dla osób pochodzących z innych języków, takich jak PHP lub C. j jest rodzajem listy, a nie tablicą. W przypadku typu listy nie sądzę, że jest to indeksowalny. Bardzo mylące, jeśli pochodzą z innych języków.
Nguai al 12.01.19

@Nguaial Typ listy można indeksować, ale można uzyskać dostęp tylko do elementów, które już istnieją - nie można utworzyć elementu, próbując zapisać w indeksie, który jest poza zakresem. j [0] = "foo" zadziała, jeśli lista zawiera już co najmniej jeden element.
Steve Mayne


25

Rób j.append(l)zamiast j[k] = li kw ogóle unikaj .


2
Krótszy (bardziej Python?) Sposób może byćj+=[l]
Oleh Prypin,

2
@BlaXpirit: Myślę, że obciąży śmietnik.
khachik

2
@BalXpirit: Biorąc pod uwagę, że zapisuje tylko kilka znaków (zwłaszcza, że ​​musisz dodać spacje, aby było możliwe do zaakceptowania) i .appendjest to o wiele bardziej powszechne (być może z jakiegoś powodu - myślę, że nieco łatwiej to zrozumieć), nie tak naprawdę lepsze w jakikolwiek sposób. (Edytuj @khachik: Nie, +=modyfikuje w miejscu)

15

Możesz także użyć listy:

j = [l for l in i]

lub wykonaj jego kopię za pomocą oświadczenia:

j = i[:]

ta druga konstrukcja jest zgrabna
javadba

2
Jeśli jedynym celem jest skopiowanie listy, możesz po prostu powiedzieć j = lista (i) Myślę, że pytanie dotyczy raczej zachowania list, a nie konkretnie potrzeby kopiowania elementów.
Steve Mayne,

10
j.append(l)

Unikaj także używania małych liter „L”, ponieważ łatwo jest pomylić je z literami „1”


7

Myślę, że to, czego szukasz, to wstawka do metody Python :

Wstawia element x w pozycji i. list.insert (i, x)

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

array.insert(1,20)

print(array)

# prints [1,2,20,3,4,5]

1
Nie ma sensu używać insertterminu, który appendzostał specjalnie przewidziany do tego celu.
holdenweb

W punkcie informacyjnym kod faktycznie jest drukowany [1, 20, 2, 3, 4, 5].
holdenweb

Wstawiłeś przy indeksie 1, przesuwając indeksy 1 i dalej. Wstawiona wartość nie kończy się na indeksie 2. Iist.insert () jest naprawdę potrzebny tylko wtedy, gdy nie chcesz dodawać elementu na końcu listy; pytanie tutaj robi dokładnie to, więc list.append () jest preferowana.
Martijn Pieters

Właściwie to, dlaczego odpowiadam na to pytanie, jestem zaskoczony: D Nie wiem, co myślałem :) To jest dokładnie „list.append ()”, która jest przyjętą odpowiedzią. Myślę, że pomaga ludziom lub daje pomysł na rozwiązanie ich problemów, więc dostaje 5 trafień.
woda

5

Możesz użyć słownika (podobnego do tablicy asocjacyjnej) dla 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

wydrukuje:

{0: 1, 1: 2, 2: 3, 3: 5, 4: 8, 5: 13}

W przypadku kolejnych wskaźników rozpoczynających się od 0, mapowanie jest zwykle niepoprawną strukturą danych, szczególnie gdy mapowania nie mają podziału ani odwracania, ponieważ nie mają one na celu przekazania żadnego konkretnego zamówienia.
Martijn Pieters

2

Jeszcze jeden sposób:

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

W tym przypadku jbędzie tablica numpy


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.