Pourquoi ce code itératif croissant de liste donne-t-il à IndexError: un index d'affectation de liste hors limites?

202

Veuillez considérer le code suivant:

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

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

print j

La sortie (Python 2.6.6 sur Win 7 32 bits) est:

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

Je suppose que c'est quelque chose de simple que je ne comprends pas. Quelqu'un peut-il clarifier cela?

Vladan
la source
9
appendest la bonne solution pour votre cas d'utilisation, mais il existe une méthode d'insertion sur la liste python qui peut s'insérer directement à la i'ème position dans la liste. j.insert(k, l)
opensourcegeek
Puis-je demander pourquoi la solution d'OP ne fonctionnerait-elle pas? Pourquoi utiliser append?
Helen

Réponses:

331

jest une liste vide, mais vous essayez d'écrire dans l'élément [0]dans la première itération, qui n'existe pas encore.

Essayez plutôt ce qui suit pour ajouter un nouvel élément à la fin de la liste:

for l in i:
    j.append(l)

Bien sûr, vous ne feriez jamais cela en pratique si vous ne vouliez que copier une liste existante. Vous feriez juste:

j = list(i)

Sinon, si vous souhaitez utiliser la liste Python comme un tableau dans d'autres langages, vous pouvez pré-créer une liste avec ses éléments définis sur une valeur nulle ( Nonedans l'exemple ci-dessous), et plus tard, écraser les valeurs dans des positions spécifiques:

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

La chose à réaliser est qu'un listobjet ne vous permettra pas d'attribuer une valeur à un index qui n'existe pas.

Steve Mayne
la source
2
D'accord, merci beaucoup. Je ne savais pas laquelle féliciter car il y a trois réponses presque identiques. C'est à mon avis le plus descriptif. Cheers
Vladan
Je peux voir que cela peut être très déroutant pour ceux qui viennent d'autres langages comme PHP ou C. j est un type de liste, pas un tableau. Avec le type de liste, je ne pense pas que ce soit en indice. Très déroutant si vous venez d'autres langues.
Nguai al
@Nguaial Le type de liste est indexable, mais vous ne pouvez accéder qu'aux éléments qui existent déjà - vous ne pouvez pas créer un élément en essayant d'écrire dans un index qui est hors de portée. j [0] = "toto" fonctionnera si la liste contient déjà au moins un élément.
Steve Mayne
54

Votre autre option consiste à initialiser j:

j = [None] * len(i)
Rsh
la source
3
Vous souhaitez utiliser len (i) plutôt que max.
Steve Mayne
26

Faites j.append(l)au lieu j[k] = let évitez kdu tout.

Khachik
la source
2
Un moyen plus court (plus pythonique?) Pourrait êtrej+=[l]
Oleh Prypin
2
@BlaXpirit: Cela mettra un fardeau au ramasse-miettes, je pense.
khachik
2
@BalXpirit: Étant donné que cela ne sauve que quelques caractères (d'autant plus que vous devez ajouter des espaces pour que cela soit acceptable) et que .appendc'est beaucoup plus courant (peut-être pour une raison - je pense que c'est un peu plus facile à comprendre), pas vraiment supérieur de quelque manière que. (Modifier @khachik: Non, +=modifie sur place)
16

Vous pouvez également utiliser une compréhension de liste:

j = [l for l in i]

ou faites-en une copie à l'aide de l'instruction:

j = i[:]
Jason Sundram
la source
cette deuxième construction est soignée
javadba
2
Si le seul objectif est de copier la liste, vous pouvez simplement dire j = list (i) Je pense que la question porte davantage sur le comportement des listes que sur le besoin spécifique d'un moyen de copier des éléments.
Steve Mayne
11
j.append(l)

Évitez également d'utiliser des «L» minuscules car il est facile de les confondre avec les 1

À M
la source
7

Je pense que l' insertion de méthode Python est ce que vous recherchez:

Insère l'élément x à la position i. list.insert (i, x)

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

array.insert(1,20)

print(array)

# prints [1,2,20,3,4,5]
Mehmet Kagan Kayaalp
la source
1
Il ne sert à rien d'utiliser insertquand a appendété fourni spécifiquement à cet effet.
holdenweb
Sur un point d'information, votre code s'imprime en fait [1, 20, 2, 3, 4, 5].
holdenweb
Vous avez inséré à l'index 1, en déplaçant les index 1 et suivants. La valeur insérée ne finit pas à l'index 2. Iist.insert () n'est vraiment nécessaire que lorsque vous ne voulez pas ajouter l'élément à la fin de la liste; la question ici fait exactement cela, donc list.append () est préférable.
Martijn Pieters
En fait, pourquoi je réponds à cette question comme ça, je suis aussi surpris: D Je ne sais pas ce que je pensais :) C'est exactement "list.append ()" qui est la réponse acceptée. Je pense que cela aide les gens ou donne une idée pour résoudre leurs problèmes, donc il obtient 5 résultats.
Mehmet Kagan Kayaalp
5

Vous pouvez utiliser un dictionnaire (similaire à un tableau associatif) pour 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

imprimera:

{0: 1, 1: 2, 2: 3, 3: 5, 4: 8, 5: 13}
Cédric
la source
Pour les indices consécutifs commençant à 0, un mappage est généralement la mauvaise structure de données, en particulier lorsque les mappages n'ont pas de découpage ou d'inversion car ils ne sont pas destinés à transmettre un ordre spécifique.
Martijn Pieters
2

Encore une façon:

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

Dans ce cas, il y jaura un tableau numpy

Alex
la source
0

Peut-être avez-vous besoin de prolonger ()

i=[1,3,5,7]
j=[]
j.extend(i)
Fred Moo
la source