Bibm@th

Forum de mathématiques - Bibm@th.net

Bienvenue dans les forums du site BibM@th, des forums où on dit Bonjour (Bonsoir), Merci, S'il vous plaît...

Vous n'êtes pas identifié(e).

#1 24-05-2016 19:29:13

Abey
Invité

Python: souci avec des listes

Bonjour,

Je viens solliciter un peu d'aide pour un programme que j'essaie d'écrire en python. Je n'ai pas beaucoup de connaissances ni d'expérience en programmation (juste quelques cours à la fac qui commencent à dater)mais, dans le cadre de la tentative d'écriture d'un programme compliqué je butte sur un phénomène que je ne parviens pas à comprendre.
J'ai isolé la partie qui me pose problème.
J'ai une grille (en fait une liste de listes) dans laquelle je souhaiterais faire des modifications aléatoires mais je voudrais garder en mémoire la grille initiale.

Voila ce que j'ai écrit:

GrilleI=[['A', 'B', 'C', 'D', 'E'], ['F', 'G', 'H', 'I', 'J'], ['K', 'L', 'M', 'N', 'O'], ['P', 'Q', 'R', 'S', 'T'], ['U', 'V', 'X', 'Y', 'Z']]
import random
Tour=4
grilleM=GrilleI

for j in range (Tour):   
   
    X1=random.randrange(5)
    X2=random.randrange(5)
    Y1=random.randrange(5)
    Y2=random.randrange(5)
   
    XX=ord(GrilleI[X1][X2])
    YY=ord(GrilleI[Y1][Y2])     
    grilleM[X1][X2]=chr(YY)
    grilleM[Y1][Y2]=chr(XX)
   
print "grille modifie", grilleM
print "grille initiale", GrilleI

Et voila le résultat dans le Shell:
grille modifie [['A', 'E', 'G', 'D', 'B'], ['F', 'C', 'H', 'I', 'J'], ['K', 'L', 'M', 'S', 'O'], ['P', 'X', 'R', 'N', 'T'], ['U', 'V', 'Q', 'Y', 'Z']]
grille initiale [['A', 'E', 'G', 'D', 'B'], ['F', 'C', 'H', 'I', 'J'], ['K', 'L', 'M', 'S', 'O'], ['P', 'X', 'R', 'N', 'T'], ['U', 'V', 'Q', 'Y', 'Z']]

Les modifications ont eu lieu dans les deux grilles, je ne trouve pas ça logique. Je me suis cassé la tête longtemps sur cela, j'ai voulu remplir une autre grille en y insérant les listes de la grille initale avec le append afin que la GrilleI ne soit jamais mentionnée dans la boucle for mais ça n'a pas marché.

Avez vous des idées ? Je suis désolée si ma façon de procéder vous semble illogique ou mal écrite. Désolée aussi si ma question est bête. J'essaie juste de comprendre ce qui ne va pas, il me semble ne jamais demander à ce que la grilleI soit changée. Toutes les suggestions sont bienvenues.

Merci pour votre aide

Laura

#2 24-05-2016 20:56:29

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 944

Re : Python: souci avec des listes

Bonsoir,

Les 2 listes pointent sur la même référence : il faut le savoir...
Si tu préfères, il s'agit de 2 noms différents pour la même liste.
Ecris plutôt :
GrilleM=list(GrilleI)
Quelques essais

>>> a = [1,2,3]
>>> b = list(a)
>>> a[1]=9
>>> a
[1,9,3]
>>> b
[1, 2, 3]
>>> b=list(a)
>>> b
[1, 9, 3]
>>> b[1]=2
>>> a
[1, 9, 3]
>>> b
[1, 2, 3]

Je ne pourrais reprendre contact que demain soir vers 18 h, donc patience...

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#3 25-05-2016 09:07:36

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 944

Re : Python: souci avec des listes

Re,

J'ai trouvé un petit créneau : il semble que la méthode suggérée ne marche pas dans ton cas. Pas le temps ce matin de chercher pourquoi.

Voilà une méthode qui marche :
je lis chaque sous-liste via une boucle, puis chaque élément de chaque sous-liste.
Chacun de ces éléments est ajouté à une liste A.
Lorsque la sous-liste est épuisée, j'ajoute A à Grille M, puis je vide A...
Voilà pour le principe.

from random import randrange

GrilleI=[['A', 'B', 'C', 'D', 'E'], ['F', 'G', 'H', 'I', 'J'], ['K', 'L', 'M', 'N', 'O'], ['P', 'Q', 'R', 'S', 'T'], ['U', 'V', 'X', 'Y', 'Z']]
GrilleM,A=[],[]

for L in GrilleI:
    for elem in L:
        A.append(elem)
    GrilleM.append(A)
    A=[]

Tour=4
for j in range (Tour):    
    X1=randrange(5)
    X2=randrange(5)
    Y1=randrange(5)
    Y2=randrange(5)  
    XX=ord(GrilleI[X1][X2])
    YY=ord(GrilleI[Y1][Y2])    
    GrilleM[X1][X2]=chr(YY)
    GrilleM[Y1][Y2]=chr(XX)

print ("Grille initiale", GrilleI)
print()
print ("Grille modifiée", GrilleM)

Exemple de fonctionnement :
Grille initiale [['A','B','C','D','E'], ['F' 'G','H','I','J'], ['K','L','M','N','O'], ['P','Q','R','S','T'], ['U','V','X','Y','Z']]

Grille modifiée [['A' 'B','L','D','Y'], ['F','G','H','I','J'], ['K','C','M','Z','O'], ['P','Q','R','S','T'], ['U' 'Z','X','E','N']]

--------------------------------------------------------------------------------

Importer tout ce qui est contenu dans random est inutile : importe depuis random ce dont tu as besoin, donc seulement randrange...
Une importation se met en début de programme.

@+

[EDIT]
Méthode plus simple :

>>> A=[1,2,3]
>>> B=A[:]
>>> B
[1, 2, 3]
>>> A=[1,3,4]
>>> B
[1, 2, 3]
>>> A
[1, 3, 4]
>>> G1=['A', 'I', 'C', 'D', 'L']
>>> G2=G1[:]
>>> G2
['A', 'I', 'C', 'D', 'L']
>>> G1[3]="W"
>>> G1
['A', 'I', 'C', 'W', 'L']
>>> G2
['A', 'I', 'C', 'D', 'L']
>>>

J'avais testé hier soir, mais ça ne marchait pas non plus chez toi...
La seule explication est "Liste de listes", mais pourquoi ?.

Voilà une solution plus courte utilisant le principe illustré ci-dessus :

from random import randrange

GrilleI=[['A', 'B', 'C', 'D', 'E'], ['F', 'G', 'H', 'I', 'J'], ['K', 'L', 'M', 'N', 'O'], ['P', 'Q', 'R', 'S', 'T'], ['U', 'V', 'X', 'Y', 'Z']]
GrilleM=[]
for i in range(len(GrilleI)):
    GrilleM.append(GrilleI[i][:])  

Tour=4
for j in range (Tour):    
    X1=randrange(5)
    X2=randrange(5)
    Y1=randrange(5)
    Y2=randrange(5)  
    XX=ord(GrilleI[X1][X2])
    YY=ord(GrilleI[Y1][Y2])    
    GrilleM[X1][X2]=chr(YY)
    GrilleM[Y1][Y2]=chr(XX)
   
print ("Grille initiale", GrilleI)
print()
print ("Grille modifiée", GrilleM)

Questions ?

Dernière modification par yoshi (25-05-2016 17:48:23)


Arx Tarpeia Capitoli proxima...

Hors ligne

#4 25-05-2016 17:40:55

Abey
Invité

Re : Python: souci avec des listes

Merci beaucoup pour ton aide.

Je vais tester tout ça (je ne vais pas avoir le temps aujourd'hui ou demain mais je pense m'y remettre Vendredi)

C'est très sympa de prendre le temps de m'aider

#5 25-05-2016 20:20:17

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 944

Re : Python: souci avec des listes

Salouut,

Ok !
Exemple de sortie de la dernière version ci-dessus :

Grille initiale [['A','B','C','D','E'], ['F','G','H','I','J'], ['K','L','M','N','O'], ['P','Q','R','S','T'], ['U','V','X','Y','Z']]

Grille modifiée [['L','B','C','D','E'], ['F','G','X','I','J'], ['K','A','M','Q','O'], ['P','N','V','S','T'], ['U','R','H','Y','Z']]


J'ai récrit ce programme avec Python 3.4. Je n'avais pas ajouter les 2 premières lignes "traditionnelles" (importantes).
En Python 2.x ce qui a l'air d'être ton cas, le programme écrit correctement est :

#!/usr/bin/env python
# -*- coding: CP1252 -*-

from random import randrange

GrilleI=[['A', 'B', 'C', 'D', 'E'], ['F', 'G', 'H', 'I', 'J'], ['K', 'L', 'M', 'N', 'O'], ['P', 'Q', 'R', 'S', 'T'], ['U', 'V', 'X', 'Y', 'Z']]
GrilleM=[]
for i in range(len(GrilleI)):
    GrilleM.append(GrilleI[i][:])  

Tour=4
for j in range (Tour):    
    X1=randrange(5)
    X2=randrange(5)
    Y1=randrange(5)
    Y2=randrange(5)  
    XX=ord(GrilleI[X1][X2])
    YY=ord(GrilleI[Y1][Y2])    
    GrilleM[X1][X2]=chr(YY)
    GrilleM[Y1][Y2]=chr(XX)
   
print "Grille initiale", GrilleI
print
print "Grille modifiée", GrilleM

Ou encore, par ex., en ligne 2 :
# -*- coding: Latin-1 -*-
C'est cette ligne qui génère des problèmes avec des caractères accentués.
Tu constates que print n'a plus de parenthèses : elles sont indispensables avec Python 3.x, print étant devenu une fonction, ce qui n'était pas le cas avec les versions 2.x

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#6 26-05-2016 20:31:12

Abey
Invité

Re : Python: souci avec des listes

Ah oui c'est pour cela que je n'arrivais à le sauver. J'ai pris un peu de temps hier soir tard (mais je ne suis pas repassée ici) et j'ai trouvé un autre moyen, la grille initiale que je veux garder en mémoire est devenue une chaine de caractère de ce genre:
Grille="ABCDE..."
Quand je veux des listes je range les caractères dans les listes et la chaine de caractères est inchangée. Si je veux la changer par une des grilles modifiées je fais le contraire (je crée une chaine dans laquelle ajoute les élèments des listes un a un. ça fait des opérations en plus mais ça tourne.
Merci

#7 13-07-2016 15:54:45

Sup
Invité

Re : Python: souci avec des listes

Bonjour,
La solution liste2=list(liste1) proposée plus haut dans la discussion ne fonctionne que pour des listes unidimensionnelles, i.e. sans imbrication. Elle ne travaille en effet qu'à un seul niveau de profondeur.
Dans le problème posé ici, il faut réaliser ce que l'on appelle une copie profonde, en important le module "copy" :
import copy
Puis en utilisant la fonction "deepcopy" :
liste2=copy.deepcopy(liste1)

#8 13-07-2016 16:05:22

yoshi
Modo Ferox
Inscription : 20-11-2005
Messages : 16 944

Re : Python: souci avec des listes

Salut,

Merci. Je ne connaissais pas ce module et j'ai donc réinventé la roue...
J'avais deviné que list(liste) ne marchait pas à cause des sous-listes : maintenant je sais pourquoi.

@+


Arx Tarpeia Capitoli proxima...

Hors ligne

#9 13-07-2016 17:03:13

tibo
Membre expert
Inscription : 23-01-2008
Messages : 1 097

Re : Python: souci avec des listes

Salut,

Intéressant ce petit module copy. Jusqu'à maintenant, pour copier une liste, je créais une liste vide puis j'ajoutais un à un les éléments de la liste de départ avec un for.


yoshi a écrit :

Importer tout ce qui est contenu dans random est inutile : importe depuis random ce dont tu as besoin, donc seulement randrange...

Dans le cas du module random c'est vrai car le risque de conflit est peu probable.
Mais pour les très gros programmes, il est en général préférable d'utiliser "import nomModule", même pour une seule fonction.
Ensuite pour executer une fonction il faut écrire "nomModule.nomFonction()
Un peu lourd, mais comme ça Python sait exactement de quelle fonction on parle dans le cas oùu plusieurs fonction aurait le même nom.

Dernière modification par tibo (13-07-2016 17:06:35)


A quoi sert une hyperbole?
----- A boire de l'hypersoupe pardi !

Hors ligne

#10 30-08-2016 09:18:37

vallatluxembourg
Membre
Lieu : Luxembourg
Inscription : 30-08-2016
Messages : 1
Site Web

Re : Python: souci avec des listes

Mais pour les très gros programmes, il est en général préférable d'utiliser "import nomModule", même pour une seule fonction.
Ensuite pour executer une fonction il faut écrire "nomModule.nomFonction()
Un peu lourd, mais comme ça Python sait exactement de quelle fonction on parle dans le cas oùu plusieurs fonction aurait le même nom.

C'est exactement comme cela qu'il faut procéder... et aussi garder dans un coin ses conventions de nommage. C'est bête, mais c'est très utile sur les très gros programmes.

Hors ligne

Pied de page des forums