2010-04-29 17 views
36

Possible en double:
Unexpected feature in a Python list of listsliste 2D a behavor bizarre lorsque vous essayez de modifier une seule valeur

Je suis relativement nouveau à Python et je ne parviens pas à travailler avec des listes 2D.

Voici mon code:

data = [[None]*5]*5 
data[0][0] = 'Cell A1' 
print data 

et est ici la sortie (formaté pour la lisibilité):

[['Cell A1', None, None, None, None], 
['Cell A1', None, None, None, None], 
['Cell A1', None, None, None, None], 
['Cell A1', None, None, None, None], 
['Cell A1', None, None, None, None]] 

Pourquoi chaque ligne la valeur sont-ils assignés?

+4

Oh boy, j'étais coincé sur ce même problème dans la journée .. :) – ktdrv

Répondre

45

Cela fait une liste avec cinq références à la même liste:

data = [[None]*5]*5 

Utilisez quelque chose comme ça au lieu qui crée cinq listes distinctes:

>>> data = [[None]*5 for _ in range(5)] 

Maintenant, il fait ce que vous attendez:

>>> data[0][0] = 'Cell A1' 
>>> print data 
[['Cell A1', None, None, None, None], 
[None, None, None, None, None], 
[None, None, None, None, None], 
[None, None, None, None, None], 
[None, None, None, None, None]] 
2

En python chaque variable est un ob ject, et donc une référence. Vous avez d'abord créé un tableau de 5 Nones, puis vous construisez un tableau avec 5 fois le même objet.

8

Comme le python library reference for sequence types, qui comprend des listes, dit

Notez également que les copies sont peu profondes; les structures imbriquées ne sont pas copiées. Cela hante souvent les nouveaux programmeurs Python; considérer:

>>> lists = [[]] * 3 
>>> lists 
    [[], [], []] 
>>> lists[0].append(3) 
>>> lists 
    [[3], [3], [3]] 

Ce qui est arrivé est que [[]] est une liste d'un élément contenant une liste vide, donc les trois éléments de [[]] * 3 sont (pointeurs vers) ce liste vide unique. La modification de l'un des éléments des listes modifie cette liste unique.

Vous pouvez créer une liste des différentes listes de cette façon:

>>> lists = [[] for i in range(3)] 
>>> lists[0].append(3) 
>>> lists[1].append(5) 
>>> lists[2].append(7) 
>>> lists 
    [[3], [5], [7]]