t1=[10,30,42,2,17,5,30,-20]
t2=[i**2 for i in range(-3,6)]
t3=[i**3 for i in range(1000) if (i%5) in [0,2,4]]
t4=[841.0]
for i in range(20):
t4.append(t4[i]/3+28)
#t5 identique à t2
t5 = []
for i in range(-3,6):
t5.append(i**2)
#t6 identique à t3
t6 = []
for i in range(1000):
if (i%5) in [0,2,4]:
t6.append(i**3)
t7 = ['ab', 'bc', 'a', 'bb']
t8 = [t7[i] for i in range(len(t7)) if 'a' in t7[i]]
t7, t8
t5, t2
len(t6)
t6 == t3
len(t1) #donne la longueur de t1
[len(L) for L in [t1,t2,t3,t4]]
L = [i for i in range(851, 854)]
L
L[0], L[1] = L[1], L[0]
L
def echange(t, i, j):
"""echange les valeurs des termes t[i] et t[j] du tableau t"""
t[i], t[j] = t[j], t[i]
# inutile de retourner t puisque les listes sont passées par référence
t = [k for k in range(10)]
t
echange(t, 1, 9)
t
M = [ [1, 2, 3], [4,5, 6] ]
M
len(M)
M[1]
M[0][2]
for i in range(len(M)):
p = len(M[i])
print('|',end='')
for j in range(p - 1):
print(M[i][j], end=' , ')
print(M[i][p - 1], end='|\n')
def dimensions(M):
return (len(M), len(M[0]))
d = dimensions([[0,1,2], [3,4,5]])
d
d[0]
d[1]
type(d)
d[0] = 4
L = [i for i in range(10)]
L
L[2] #élément en position 3
#dernier élément
L[len(L) - 1]
L
On peut indexer les éléments à partir de la fin Le dernier a pour index -1 Le premier cad L[0] a pour index -len(L)
L[-1]
L[-len(L)]
Découpage de tranches ou slicing
L
# la tranche des éléments de L entre l'index 2
#et l'index 5 exclu, c'est une liste
L[2:5]
#trois derniers éléments
L[-3:]
#les trois premiers
L[:3]
#tous sauf les trois premiers et les trois derniers
L[3:-3]
#les trois premiers suivis des trois derniers
L[:3] + L[-3:]
# dix derniers éléments de t3
t3[-10:]
# éléments de t3 sauf les 250 premiers et les 250 derniers
t3[250:-250]
# cinq premiers éléments de t4 suivie des cinq derniers de t4
t4[:5]+t4[-5:]
li = [5, 6, 9, 12]
id(li)
li.append(-14)
li
id(li) #l'adresse mémoire de li n'est pas modifiée par append
lj = [7, 8, 10]
id(lj)
lj = lj + [14]
lj
id(lj) #une nouvelle adresse mémoire a été affectée à lj
li.extend(lj)
li
id(li) #l'adresse mémoire de li n'est pas modifiée par extend
li[:4]
lj = li[:4] + lj
lj
lj.insert(1, 13) #insertion de 13 en position 1
lj
lj[3:4] = [100] #insertion de 100 à la place de 9 en position 3
lj
lj[3:3] = [99] #insertion de 99 en position 3
lj
L = [42, "BCPST", 2 < 3, 3.14, [5, 4]]
del L[2] #suppression de l'élément en position 2
L
L[1:2] = [] #suppression de l'élément en position 1
L
val = L.pop(1) #suppression de l'élément en position 1 et récupération de la valeur
val
L
L = [i for i in range(851, 854)]
Parcours sur les index
for i in range(len(L)):
print(i, L[i])
Parcours sur les valeurs
for element in L:
print(element)
Carrés de L
[L[i] ** 2 for i in range(len(L))]
[ element ** 2 for element in L]
t5 = [t2[2*i+1] for i in range(3)]
# t5 contient les trois premiers éléments de t2 d'indice impair
t2, t5
t2[1:7:2] #trois premiers éléments de t2 d'indice impair par slicing
t6 = [x**2 for x in t2]
# t6 contient les carrés des éléments de t2
t6
t7 = [(x,y) for x in [1,2,3] for y in [3,1,4] if x != y]
t7 contient les couples (i,j) avec i in [1,2,3] et j in [3,1,4] et i!=j
Liste des éléments d'indice pair de t1
t1
# Par slicing
t1[::2]
#Par liste en compréhension
[t1[i] for i in range(0, len(t1), 2)]
[t1[i] for i in range(0, len(t1)) if i%2 == 0]
L = []
for i in range(0, len(t1)):
if i%2 == 0:
L.append(t1[i])
Liste des termes pairs de t1
#par liste en compréhension
[e for e in t1 if e%2 == 0]
#avec append
pair = []
for e in t1:
if e % 2 == 0:
pair.append(e)
print(pair)
def somme1(t):
s = 0
for i range(len(t)):
s = s + t[i]
return s
def somme(tab):
"""somme des éléments d'un tableau, redéfinition de sum"""
s = 0
for terme in tab:
s += terme
return s
somme(t1)
def moyenne(tab):
"""moyenne des éléments d'un tableau sous forme de flottant"""
return float(somme(tab))/len(tab)
moyenne(t2)
moyenne des carrés de t2
moyenne([e**2 for e in t2])
Racine carré
from math import sqrt
sqrt(2)
2 ** 0.5
2 ** (1/2)
2**1/2
def ecart_type1(tab):
"""écart-type des éléments d'un tableau avec la formule de Konig"""
tabcarre = [x**2 for x in tab]
return (moyenne(tabcarre)-moyenne(tab)**2)**0.5
ecart_type1(t2)
def ecart_type2(tab):
"""écart-type des éléments d'un tableau avec la définition et sans listes en compréhension"""
m = moyenne(tab) # m est un flottant
s = 0. #s sera un flottant
# s recevra la somme des carrés des écarts à la moyenne
for x in tab:
s = s +(x - m)**2
return (s/len(tab))**0.5
ecart_type2(t2)
def maximum(tab):
"""retourne le maximum d'un tableau, redéfinition de max"""
m = tab[0]
for terme in tab[1:]: # ou for k in range(1, len(tab))
if terme > m: # ou if tab[k] > m
m = terme # ou m = tab[k]
return m
def maximum2(tab):
"""retourne le maximum d'un tableau, redéfinition de max"""
m = tab[0]
for i in range(1, len(tab)):
if tab[i] > m:
m = tab[i]
return m
def position_maximum(tab):
"""retourne la première position où le maximum est atteint"""
pos,maxi = 0,tab[0]
for i in range(1, len(tab)):
if tab[i] >= maxi: # si on met une inégalité large, la fonction retourne la dernière position où le maximum est atteint
pos,maxi = i,tab[i]
return pos
def liste_positions_maximum(tab):
"""retourne le maximum et la liste des positions où il est atteint"""
tmaxi, maxi = [0],tab[0]
for i in range(1,len(tab)):
if tab[i] > maxi:
tmaxi,maxi = [i],tab[i]
elif tab[i] == maxi:
tmaxi.append(i)
return tmaxi,maxi
maximum([3,4,4,2])
position_maximum([3,4,4,2])
liste_positions_maximum([3,4,4,2])
def croissante(t):
"""Retourne un booleen indiquant si une liste est croissante"""
for k in range(len(t) - 1):
if t[k] > t[k + 1]:
return False
return True
import operator #module permettant de récupérer les opérateurs de base sous forme de fonction
def monotone(t):
"""Retourne un booleen indiquant si une liste est monotone"""
assert len(t) >= 2, "La liste doit contenir au moins deux éléments"
#on choisit la fonction de comparaison selon l'ordre des deux premiers éléments
if t[0] < t[1]:
comparaison = operator.gt
else:
comparaison = operator.lt
for k in range(1, len(t) - 1):
if comparaison(t[k], t[k + 1]):
return False
return True
t = [k for k in range(10)]
print(t)
croissante(t)
t[::-1] #inversion d'une liste par slicing
croissante(t[::-1] )
monotone(t)
monotone([0])
Une première version du calcul des termes $u_{n}$ où l'on mémorise les termes déjà calculés dans une liste.
def suite_exo11V1(n):
u = [1]
for i in range(1, n + 1):
s = 0
j = i - 1
for k in range(0, i):
s = s + (j + k)*u[k]
u.append(s)
return u[-1]
[suite_exo11V1(n) for n in range(6)]
Une seconde version où l'on mémorise simplement le terme précédent $u_{n}$, la somme $\sum_{k=0}^{n}u_{k}$ et la somme pondérée $\sum_{k=0}^{n}ku_{k}$.
def suite_exo11V2(n):
somme = 1
sommepond = 0
u = 1
for i in range(1, n + 1):
u = (i - 1)*somme + sommepond
somme = somme + u
sommepond = sommepond + i*u
return u
[suite_exo11V2(n) for n in range(6)]
def compartab(t1, t2):
"""Compare si deux tableaux sont égaux"""
taille1 = len(t1)
if taille1 != len(t2):
return False
for k in range(taille1):
if t1[k] != t2[k]:
return False
return True
def compartab2(t1, t2):
"""Compare si deux tableaux sont égaux avec l'itérateur zip"""
if len(t1) != len(t2):
return False
for e1, e2 in zip(t1, t2):
if e1 != e2:
return False
return True
from random import randint
alea1 = [randint(0, 20) for _ in range(10)]
alea2= [randint(0, 20) for _ in range(10)]
alea1
alea2
compartab2(alea1, alea2)
compartab(alea1, alea2)
compartab([1,0, 1], [1,0,1]), compartab2([1,0, 1], [1,0,1])
def inversion(t):
L = []
for e in t:
L.insert(0, e)
return L
def inversion2(t):
L = []
for k in range(len(t) - 1, -1, -1):
L.append(t[k])
return L
def inversion3(tab):
"""idem mais avec une liste en compréhension"""
return [tab[i] for i in range(-1,-len(tab)-1,-1)]
inversion(alea1)
inversion2(alea1)
#vérification avec un slicing
alea1[::-1]
def remplace(t, x, y):
"""Remplace dans t toutes les occurences de x par y"""
for k in range(len(t)):
if t[k] == x:
t[k] = y
alea1
remplace(alea1, 4, 7)
alea1
def remplace2(t, x, y):
"""Remplace dans t toutes les occurences de x par y
Retourne une nouvelle liste"""
def auxiliaire(e):
"""Fonction auxiliaire"""
if e != x:
return e
return y
return list(map(auxiliaire, t))
def remplace3(tab,x,y):
"""Remplace dans t toutes les occurences de x par y
Retourne une nouvelle liste"""
return [element if element != x else y for element in tab]
alea1
remplace2(alea1, 20, 0)
En Python, on peut considérer que les variables de types simples (int
, bool
, float
) sont bien l'association d'un nom et d'une valeur.
Les variables de type list
sont différentes. Dans un autre langage comme le C
, on dirait qu'il s'agit de pointeurs c'est-à-dire de variables dont les valeurs sont des adresses de zone mémoires où sont stockées les valeurs proprement dites. On parle aussi de référence pour la valeur d'une liste et ce type de mécanisme est appelé indirection.
Par exemple lorsqu'on écrit L = [1, 3.14, [2, 3]]
, la valeur de L n'est pas [1, 3.14, [2, 3]]
mais l'adresse de la zone mémoire où est stockée [1, 3.14, [2, 3]]
Ainsi lorsqu'on assigne la valeur de L
à une autre liste T
, on donne à T
l'adresse mémoire associée à L
, celle qui pointe vers la zone mémoire où est stockée [1, 3.14, [2, 3]]
. Cette dernière peut être vue comme une série d'octets contigus où sont stockés l'entier 4
, le flottant 3.14
et la valeur de la liste [2, 3]
. Mais la valeur de la liste [2, 3]
est elle même une adresse mémoire, celle de la zone mémoire contigue où sont stockés les entiers 2
et 3
.
Avec les listes de listes, on peut donc avoir plusieurs niveaux d'indirections imbriquées les unes dans les autres. Il faut donc utiliser la fonction deepcopy
du module copy
pour réaliser une vraie copie (dite copie profonde), en cassant les références des listes (on dit aussi déréférencer) et en créant de nouvelles zones mémoires pour stocker les mêmes données que la liste de listes source.
L = [[851, 852], [853, 854]]
M = L
L[0][1], M[0][1]
L[0][1] = 833
L, M
N = L[:]
L[0][1] = 854
L, N
from copy import deepcopy
P = deepcopy(M)
P, M
M[0][1] = 855
M, P
Lien vers l'exemple ci-dessous sur PythonTutor :
L = [0,0,0]*4
K = [[0,0,0]] + [[0,0,0]] + [[0,0,0]] + [[0,0,0]]
N = [[0,0,0]]*4
N[1][1] = 2
M = [[0,0,0] for i in range(4)]
M[1][1] = 2
P = [[0 for i in range(3)] for j in range(4)]
P[1][1] = 2
Q = [[0]*3 for j in range(4)]
R = []
for nligne in range(4):
ligne = []
for ncol in range(3):
ligne.append(0)
R.append(ligne)
S = []
for nligne in range(4):
S = S + [0]*3
Lien vers un autre exemple sur PythonTutor :
def zeros(n,p):
mat = []
for nligne in range(n):
ligne = []
for ncol in range(p):
ligne.append(0)
mat.append(ligne)
return mat
def zeros2(n,p):
"""Retourne la matrice nulle de n lignes et p colonnes"""
return [[0]*p for i in range(n)]
def zeros3(n,p):
"""Mauvaise fonction car on réplique toujours
la meme ligne"""
return [[0]*p]*n
a = zeros3(2,3) #mauvaise copie
a
a[0][0] = 1
a
b = zeros(2,3) #bonne copie
b
b[0][0] = 1
b
deepcopy
)¶Lien vers un exemple sur PythonTutor :
def copie0(mat):
"""Vraie copie de mat sans partage de données"""
n, p = dimensions(mat)
mat2 = []
for nligne in range(n):
ligne = []
for ncol in range(p):
ligne.append(0)
mat2.append(ligne)
return mat2
def copie01(mat):
"""Vraie copie de mat sans partage de données"""
n, p = dimensions(mat)
mat2 = zeros2(n, p )
for i in range(n):
for j in range(p):
mat2[i][j] = mat[i][j]
return mat2
def copie(m):
"""retourne une copie de la matrice m"""
nlines,ncols = dimensions(m)
n = zeros(nlines,ncols) # matrice copie
for i in range(nlines):
for j in range(ncols):
n[i][j] = m[i][j]
return n
def copie1(m):
"""copie de matrice avec une liste en compréhension"""
return [[m[i][j] for j in range(len(m[0]))] for i in range(len(m))]
def copie2(m):
"""retourne une copie de la matrice m"""
n = [] #matrice copie
nlines,ncols = dimensions(m)
for i in range(nlines):
ligne = [] #vecteur ligne
for j in range(ncols):
ligne.append(m[i][j])
n.append(ligne)
return n
def dimensions(M):
return (len(M), len(M[0]))
def somme_matrice(m,n):
"""retourne la matrice somme de deux matrices m et n"""
(nlines, ncols) = dimensions(m)
if dimensions(n) != (nlines, ncols):
return None
s = zeros(nlines,ncols)
for i in range(nlines):
for j in range(ncols):
s[i][j] = m[i][j]+n[i][j]
return s
def somme_matrice1(m,n):
"""retourne la matrice somme de deux matrices m et n"""
assert dimensions(m)==dimensions(n), "Les matrices n'ont pas la même dimension"
return [[m[i][j]+n[i][j] for j in range(len(m[0]))] for i in range(len(m))]
def somme_matrice2(m,n):
"""retourne la matrice somme de deux matrices m et n"""
assert dimensions(m)==dimensions(n), "Les matrices n'ont pas la même dimension"
s = []
for i in range(len(m)):
ligne = []
for j in range(len(m[0])):
ligne.append(m[i][j]+n[i][j])
s.append(ligne)
return s
def multscal_matrice(m,t):
"""multiplie tous les coefficients de la matrice m par le scalaire t"""
nlines,ncols=dimensions(m)
s=zeros(nlines,ncols)
for i in range(nlines):
for j in range(ncols):
s[i][j]=m[i][j]*t
return s
def multscal_matrice1(m,t):
"""multiplie tous les coefficients de la matrice m par la scalaire t"""
return [[m[i][j]*t for j in range(len(m[0]))] for i in range(len(m))]
def transpose(m):
"""retourne la transposée d'une matrice"""
nlines,ncols = dimensions(m)
s = zeros(ncols,nlines)
for i in range(ncols):
for j in range(nlines):
s[i][j] = m[j][i]
return s
def transpose1(m):
"""retourne la transposée d'une matrice"""
return [[m[i][j] for i in range(len(m))] for j in range(len(m[0]))]
def prod_matrice(m,n):
"""retourne la matrice poduit de m par n"""
mlines,mcols = dimensions(m)
nlines,ncols = dimensions(n)
if mcols != nlines:
return "Les dimensions ne sont pas compatibles"
p = zeros(mlines,ncols)
for i in range(mlines):
for j in range(ncols):
#p[i][j] = 0
for k in range(mcols): # ou nlines c'est pareil
#p[i][j] = p[i][j] + m[i][k]*n[k][j]
p[i][j] += m[i][k]*n[k][j]
return p
def prod_matrice1(m,n):
"""retourne la matrice poduit de m par n"""
assert dimensions(m)[1]==dimensions(n)[0], "Les dimensions ne sont pas compatibles"
return [[sum([m[i][k]*n[k][j] for k in range(len(m[0]))]) for j in range(len(n[0]))] for i in range(len(m))]
def prod_matrice2(m,n):
"""retourne la matrice poduit de m par n"""
assert dimensions(m)[1]==dimensions(n)[0], "Les dimensions ne sont pas compatibles"
p = []
for i in range(len(m)):
ligne = []
lignem = m[i] #on stocke la ligne de m dans un pointeur
for j in range(len(n[0])):
coef = 0
for k in range(len(m[0])):
coef += lignem[k]*n[k][j]
ligne.append(coef)
p.append(ligne)
return p
def diagonale(n,x):
"""Retourne une matrice diagonale avec que des x sur la diagonale"""
return [[x if i == j else 0 for j in range(n)] for i in range(n)]
def puissance_mat(m,exposant):
"""Retourne la puissance de la matrice m d'exposant donné"""
nlines,ncols = dimensions(m)
assert nlines==ncols,"La matrice doit être carré"
p = diagonale(nlines,1)
for i in range(exposant):
p = prod_matrice2(p,m)
return p
## Exercice 14
def est_symetrique(m):
"""Retourne un booleen indiquant si la matrice m est symetrique"""
n, p = dimensions(m)
if n != p:
return False
for i in range(n):
for j in range(i):
if m[i][j] != m[j][i]:
return False
return True
def est_symetrique2(m):
n, p = dimensions(m)
if n != p:
return False
return m == transposition(m)
def sommevect1(t1, t2):
taille1 = len(t1)
if taille1 != len(t2):
return None
t = []
for k in range(taille1):
t.append(t1[k] + t2[k])
return t
def sommevect2(t1, t2):
assert len(t1) == len(t2), "les vecteurs doivente etre de meme longueur"
return [e1 + e2 for (e1, e2) in zip(t1, t2)]
def sommevect3(t1, t2):
assert len(t1) == len(t2), "les vecteurs doivente etre de meme longueur"
return list(map(sum, zip(t1, t2)))
sommevect1([1,2], [3,4]), sommevect2([1,2], [3,4]), sommevect3([1,2], [3,4])
def sommes_cumulees(t):
"""Complexité linéraire par rapport à la taille de la liste t"""
taille = len(t)
cumul = [t[0]] + [0]*(taille - 1)
for k in range(1, taille):
cumul[k] = cumul[k - 1] + t[k]
return cumul
t1
sommes_cumulees(t1)
def deux_plus_grosV1(t):
"""Retourne les deux plus grands elements du tableau/liste t.
t est supposé avoir au moins 2 éléments"""
taille = len(t)
if taille < 2:
return None
#on initialise gros avec les deux premiers éléments dans l'ordre décroissant
if t[0] > t[1]:
gros = t[:2]
else:
gros = t[1::-1]
#on parcourt le tableau à partir de la position 2 (troisieme element)
for k in range(2, len(t), 1):
#on insère l'élément courant à sa place dans la liste des deux plus gros
courant = t[k]
j = 0
while j < 2 and gros[j] > courant:
j += 1
if j == 0:
gros = [courant, gros[0]]
elif j == 1:
gros = [gros[0], courant]
return gros
deux_plus_grosV1([12, 4, 12, 1, 7, 3, 12,5])
def deux_plus_gros_rec(t):
"""Retourne les deux plus grands elements du tableau/liste t.
t est supposé avoir au moins 2 éléments. Fonction récursive"""
taille = len(t)
if taille < 2:
return None
if taille == 2:
if t[0] > t[1]:
return t[:2]
elif t[0] < t[1]:
return t[1::-1]
else:
return t[:1]
else:
gros = deux_plus_gros_rec(t[:-1])
j = 0
courant = t[-1]
while j < len(gros) and gros[j] >= courant:
j += 1
if j == 0:
return [courant, gros[0]]
elif j == len(gros) - 1 and courant != gros[0]:
return [gros[0], courant]
else:
return gros
def deux_plus_grosV2(t):
"""Retourne les deux plus grands elements du tableau/liste t.
t est supposé avoir au moins 2 éléments.
Dans cette version, on insère le sdecond plus gros uniquement s'il est distinct du plus gros"""
taille = len(t)
if taille < 2:
return None
#on initialise gros avec les deux premiers éléments dans l'ordre strictement décroissant
if t[0] > t[1]:
gros = t[:2]
elif t[0] < t[1]:
gros = t[1::-1]
else:
gros = t[:1]
#on parcourt le tableau à partir de la position 2 (troisieme element)
for k in range(2, len(t), 1):
#on insère l'élément courant à sa place dans la liste des deux plus gros
courant = t[k]
j = 0
while j < len(gros) and gros[j] >= courant:
j += 1
if j == 0:
gros = [courant, gros[0]]
elif j == len(gros) - 1 and courant != gros[0]:
gros = [gros[0], courant]
return gros
deux_plus_grosV2([12, 4, 12, 1, 7, 3, 12,5])
Si tous les éléments sont identiques, la liste renvoyée est de taille 1.
deux_plus_grosV2([12, 12, 12])
deux_plus_gros_rec([12, 4, 12, 1, 7, 3, 12,5])
deux_plus_gros_rec([12, 12, 12])
def permutelignes(A,i,j):
"""permute les lignes i et j de la matrice m"""
nlines,ncols = dimensions(A)
assert repr(type(i))==repr(type(j))=="<class 'int'>" and 0<=i<nlines and 0<=j<nlines, \
"i et j doivent être des entiers compris entre 0 et le nombre de lignes de la matrice"
A[i],A[j] = A[j],A[i]
def rempl(A,x,y):
"""remplace toutes les occurences de x dans A par y"""
nlines,ncols = dimensions(A)
for i in range(nlines):
for j in range(ncols):
if A[i][j] == x:
A[i][j] = y
def pascal(n):
"""Retourne les n premières lignes du triangle de Pascal"""
triangle = [[1]]
for i in range(1, n):
ligne = [1]
for j in range(1, i):
ligne.append(triangle[i-1][j] + triangle[i-1][j-1] )
ligne.append(1)
triangle.append(ligne)
return triangle
pascal(5)