cerhu > comp.lang.* > comp.lang.python

Fabrice (30/01/2018, 00h39)
Bonjour,

je voulais remplir un tableau avec des nombres aléatoires mais j'ai 50
fois la même ligne !

j'ai fait :

import matplotlib.pyplot as plt
import random

image = [[0]*50]*50

for ligne in range(50):
for pixel in range(50):
image[ligne][pixel] = random.randint(0, 10)

plt.imshow(image,cmap='gray')
plt.show()

Pourquoi ?

Merci,
Fabrice.
Benoit Izac (30/01/2018, 08h19)
Bonjour,

Le 29/01/2018 à 23:39, Fabrice a écrit dans le message
<5a6fa2b6$0$7180$426a74cc> :

> je voulais remplir un tableau avec des nombres aléatoires mais j'ai 50
> fois la même ligne !
> j'ai fait :
> import matplotlib.pyplot as plt
> import random
> image = [[0]*50]*50


Le problème est là. Tu crées une liste contenant 50 fois une référence
vers la même liste qui contient 50 zéros :

>>> image = [[0]*50]*50
>>> id(image[0]) 140001800012424
>>> id(image[1]) 140001800012424


Alors qu'en faisant comme cela :
Nicolas (30/01/2018, 10h53)
Bonjour,

Pour mieux comprendre la réponse de Benoit, il faut bien comprendre la
notion de variables mutables et non mutables :
[..]

Sinon :

- La largeur et la hauteur de l'image devraient être des variables.
D'une part, c'est plus compréhensible, et d'autre part, cela évite les
erreurs lorsque l'une ou l'autre sera modifiée.

largeur = 50
hauteur = 50
image = [[0]*largeur for _ in range(hauteur)]
for ligne in range(hauteur):
for pixel in range(largeur):
image[ligne][pixel] = random.randint(0, 10)

- Une petite amélioration est d'utiliser les tailles des listes pour les
parcourir :

largeur = 50
hauteur = 50
image = [[0]*largeur for _ in range(hauteur)]
for ligne in range(len(image)):
for pixel in range(len(image[0])):
image[ligne][pixel] = random.randint(0, 10)

- Mais pas besoin de créer les listes avant de les remplir. Autant les
créer avec le bon contenu dès le départ :

largeur = 50
hauteur = 50
image = []
for ligne in range(hauteur) :
pixels = []
for pixel in range(largeur) :
pixels.append(random.randint(0, 10))
image.append(pixels)

- La même chose mais en plus pythonique :

largeur = 50
hauteur = 50
image = [[random.randint(0, 10) for _ in range(largeur)] for __ in
range(hauteur)]

A noter que les _ et __ n'ont rien de particulier. Ce sont des variables
comme les autres. On les utilise pour indiquer que ces variables ne
servent à rien si ce n'est à itérer dans la boucle for.

Nicolas
marc.marc (31/01/2018, 10h25)
Bonjour,
je ne réponds pas à la question, mais pour ce genre d'opération il vaut
bien mieux à mon avis utiliser les tableaux (arrays) numpy, sur lesquels
on peut de plus faire toutes sortes de calculs, que les listes:

import numpy as np
import pylab as pl

image = np.random.randint(low=0,high=10,size=(50,50))
pl.imshow(image,cmap="gray")
pl.show()

Amicalement.
Marc

Le 29/01/2018 à 23:39, Fabrice a écrit :
[..]
Fabrice (31/01/2018, 17h15)
Le 30/01/2018 à 07:19, Benoit Izac a écrit :

> 140001800012424
> 140001800012424
> Alors qu'en faisant comme cela :
> 140001800012936
> 140001800012744


je suis surpris que [[0]*50]*50 et [[0]*50 for _ in range(50)] ne
fassent pas la même chose !

En tout cas merci Benoit,
cordialement,
Fabrice.

Fabrice (31/01/2018, 17h17)
Le 30/01/2018 à 09:53, Nicolas a écrit :
> Bonjour,
> Pour mieux comprendre la réponse de Benoit, il faut bien comprendre la
> notion de variables mutables et non mutables :
> [..]


Le pire, c'est que j'ai suivi le MOOC fun Python 3 et que j'avais
entendu parler des objets mutables ou non :-(

J'adore la solution :

> image = [[random.randint(0, 10) for _ in range(largeur)] for __ in
> range(hauteur)]


Merci Nicolas pour votre réponse très pédagogique,
cordialement,
Fabrice.

Fabrice (31/01/2018, 17h23)
Le 31/01/2018 à 09:25, marc.marc a écrit :
> Bonjour,
> je ne réponds pas à la question, mais pour ce genre d'opération il vaut
> bien mieux à mon avis utiliser les tableaux (arrays) numpy, sur lesquels
> on peut de plus faire toutes sortes de calculs, que les listes:


Sans répondre à la question explicite, vous répondez à une question non
formulée.
Je suis prof de maths et je dois enseigner l'algorithmique (un bien
grand mot pour ce niveau) en seconde.
Le programme conseille Python mais nous ne devons pas enseigner Python,
juste illustrer nos algos en programmant un peu.

Je dois donc rester très simple sur les subtilités de python.

Du coup, votre proposition d'utiliser numpy avec les "array" me semble
sympathique.

Merci pour cette piste,
cordialement,
Fabrice.
Benoit Izac (31/01/2018, 19h50)
Bonjour,

Le 31/01/2018 à 16:15, Fabrice a écrit dans le message
<5a71dd90$0$3420$426a74cc> :

>> je suis surpris que [[0]*50]*50 et [[0]*50 for _ in range(50)] ne

> fassent pas la même chose !


[[0]*50]*50 : je crée un objet de type int qui vaut 0, puis une liste de
50 éléments qui référencent tous cet objet int(0), puis une liste de 50
éléments qui référencent tous cette unique liste [0]*50.

[[0]*50 for _ in range(50)] : je fais 50 fois "je crée un objet de int
qui vaut 0, puis une liste de 50 éléments qui référencent tous cet objet
int(0)" et je mets à chaque fois la référence dans une liste. C'est
donc équivalent à :

l = []
for _ in range(50):
l.append([0]*50)
Discussions similaires
Comment remplir un tableau à partir de données d'un autre tableau

remplir un tableau

remplir un tableau à partir d'une liste présentant les meme informations que dans le tableau

remplir un tableau en vba


Fuseau horaire GMT +2. Il est actuellement 19h29. | Privacy Policy