2010-12-13 59 views
2

J'ai un problème étrange avec une tâche que j'ai. Nous sommes supposés implémenter une classe matricielle. Eh bien, ce n'est pas si difficile, mais Python ne fera tout simplement pas ce que je lui dis. Mais je suis sûr qu'il y a une explication.Liste/matrice ne sauvegarde pas les valeurs correctes

Le problème est que, dans le code suivant, j'essaie d'enregistrer des valeurs (fournies dans une liste) dans une matrice.

class simplematrix: 
    matrix = [[]] 
    def __init__(self, * args): 
     lm = args[0] 
     ln = args[1] 
     values = args[2] 
     self.matrix = [[0]*ln]*lm 

     for m in range(lm): 
      for n in range(ln): 
       self.matrix[m][n] = values[(m*ln)+n] 

vals = [0,1,2,3,4,5] 
a = simplematrix(2,3,vals) 

Lorsque je tente d'imprimer la matrice, je vous attendre à obtenir [[0,1,2], [3,4,5]], que je reçois si je le lance à la main, sur un morceau de papier. Si j'imprime la matrice à partir de Python, j'obtiens [[3,4,5], [3,4,5]] à la place. Quelqu'un peut-il me dire pourquoi Python agit comme ça, ou si j'ai fait une erreur stupide quelque part? :)

Répondre

2

Le problème est dans [[0]*ln]*lm. Le résultat se compose de lmréférences à la même liste, donc lorsque vous modifiez une ligne, toutes les lignes semblent changer.

Essayez:

self.matrix = [[0]*ln for i in xrange(lm)] 
+0

Ah d'accord. Merci beaucoup pour la réponse rapide et l'explication. Je ne vois pas l'utilisation de faire des références à la même liste plusieurs fois, donc je n'aurais jamais compris moi-même :) Encore une fois - merci. – Casper

+1

Vous êtes les bienvenus. Tout le monde se fait prendre par là à un moment donné. – NPE

1

Le problème est que self.matrix = [[0]*ln]*lm ne vous donne pas une liste de lm sous-listes séparées, mais une liste de références à lm la même liste unique [[0]*ln].

Essayez

self.matrix = [[0]*ln for i in range(lm)] 

(Si vous êtes sur Python 2, utilisez xrange(lm) à la place).

+0

Quelle est la différence entre xrange et gamme? – Casper

+0

xrange ne stocke essentiellement les éléments de la liste que lorsqu'il en a besoin, donc si vous utilisez des données avec de grandes structures de liste, beaucoup moins de mémoire est utilisée. C'est en fait un peu plus compliqué car xrange renvoie un objet xrange plutôt qu'une liste, mais pour autant que vous le sachiez, c'est pour réduire l'utilisation de la mémoire. – TartanLlama

2

Les réponses de Tim et aix corriger votre erreur, mais cette étape est même pas nécessaire, vous pouvez faire tout cela en une seule ligne à l'aide d'une compréhension de la liste:

self.matrix = [[values[m*ln+n] for n in range(ln)] for m in range(lm)] 

vous pouvez aussi dire:

vals = range(6) 

contrairement à ce que vous avez déjà. Cela range votre code et le rend plus Pythonique.

+0

Wow, c'est compact, mais beaucoup plus agréable. Merci pour le conseil. – Casper

+0

Pas de problème, c'est la beauté de Python pour vous. – TartanLlama