2017-04-23 2 views
0

J'ai un code qui se lit comme:retournant toujours le même élément

def xgauss(self): 

    m, n = self.m, self.n 

    M = self.copy() 

    for k in range(n): 
     for i in range(k + 1, m): 
      yield M 
      if not likezero(M[i][k]): 
       lam = M[i][k]/M[k][k] 
       M[i] = M[i] - lam * M[k] 

    yield M 

Pour est maintenant suffisant pour dire que likezero retourne true si la valeur est inférieure à la précision (pour les comparaisons numériques) ;-)

Mon objectif ici est de retourner chaque itération de l'algorithme d'élimination de Gauss à des fins d'étude (en classe).

J'ai quelques entrées de test comme:

In [77]: A 
Out[77]: 
Matrix([ 
     [  1,  4,  1], 
     [  1,  6,  -1], 
     [  2,  -1,  2] 
     ]) 

In [78]: Ab 
Out[78]: 
Matrix([ 
     [  1,  4,  1,  7], 
     [  1,  6,  -1,  13], 
     [  2,  -1,  2,  5] 
     ]) 

Bizarre ou non, quand je l'appelle le générateur sur la matrice Ab (sur AI également obtenir le même comportement), je suis arrivé:

In [76]: list(Ab.xgauss()) 
Out[76]: 
[Matrix([ 
     [  1,  4,  1,  7], 
     [  0,  2,  -2,  6], 
     [  0,  0,  -9,  18] 
     ]), Matrix([ 
     [  1,  4,  1,  7], 
     [  0,  2,  -2,  6], 
     [  0,  0,  -9,  18] 
     ]), Matrix([ 
     [  1,  4,  1,  7], 
     [  0,  2,  -2,  6], 
     [  0,  0,  -9,  18] 
     ]), Matrix([ 
     [  1,  4,  1,  7], 
     [  0,  2,  -2,  6], 
     [  0,  0,  -9,  18] 
     ])] 

C'est la bonne réponse (devrait être seulement la dernière itération), mais je ne peux pas voir chaque étape, le générateur retourne le résultat de la matrice dans toutes les itérations. Je n'ai aucune idée de ce qui peut arriver.

Répondre

6

Dans votre générateur, vous avez une valeur M, qui est une instance de votre classe. Vous cédez le même objet à chaque fois. À chaque itération, vous modifiez l'objet. Le générateur ne donne pas de copie de M, il renvoie M, de même que les fonctions ne retournent pas de copies, elles renvoient des références.

Lorsque vous créez une liste des résultats du générateur, vous créez une liste contenant de nombreuses références au même objet. L'impression de la liste vous montre le même objet plusieurs fois, montrant son dernier état.

BTW, ce comportement de Python (pas de copies implicites, beaucoup de références) est couvert plus en détail dans mon discours PyCon: Python Names and Values.

+0

Diaporama très cool, même si quelqu'un a compris ces concepts. Peut-être que vous voulez ajouter un avertissement que vous avez fait, cependant. – gyre