def del_pairs(tab: list)->list:
'''
cette fonction supprime les éléments pairs présents dans une liste et renvoie la liste modifiée
'''
i=0
while i < len(tab):
if tab[i] % 2 == 0:
tab.pop(i) # supprime l'élément d'indice i dans la liste tab
i = i+1
return tab
liste = [1, 2, 4, 5, 8, 7, 9, 6, 8, 10]
print(del_pairs(liste))
>>> [1, 4, 5, 7, 9, 8]
→ on constate que les nombres pairs ne sont pas tous supprimés, alors qu'aucune erreur n'est générée...
La cause : on modifie la liste en cours de boucle → effet de bord sur un objet mutable, la liste.
Une solution : créer une nouvelle liste à partir de la première, et laisser celle-ci inchangée :
def del_pairs(tab: list)->list:
'''
Cette fonction supprime les éléments pairs présents dans une liste et renvoie la liste modifiée
'''
tab2 = [] # ou copie = tab[:], ou utilisation du module 'copy'
i = 0
while i < len(tab):
if tab[i] % 2 != 0:
tab2.append(tab[i]) # supprime l'élément d'indice 'i' dans la liste 'copie'
i = i+1
return tab2
liste = [1, 2, 4, 5, 8, 7, 9, 6, 8, 10]
print(del_pairs(liste))
>>> [1, 5, 7, 9]
# code n°1
def fct(i):
if i > 0:
return True
else :
return False
j = -3
fct(j)
print(j)
→ ainsi modifié, le code n'a plus d'effet de bord.
# code n°2
def ajout(l, i):
return l + [i]
l = [4, 7, 3]
print(ajout(l, 2)) # [4, 7, 3, 2]
print(l) # [4, 7, 3]
Le code de départ ne renvoie pas la même chose pour deux appels identiques, de plus il modifie la liste l. il est donc nécessaire de renvoyer une nouvelle liste, constituée de la concaténation de l et de l'élément [i] pour ne pas la modifier directement, et bien sur de la passer en argument.
# code n°3
def incremente(x):
return x + 1
y = 5
print(incremente(y))
→ toujours passer la "variable" en argument de la fonction. On remarque que la fonction ne modifie pas cette variable.
# code n°4
def empile(ma_pile, valeur):
p2 = ma_pile + [valeur]
return p2
print(empile([], 5))
Même problème qu'au code n°2.
# code n°5
def volume_sphere(r):
pi = 3.1415
return (4/3)*pi*r**3
print(volume_sphere(4))
Pas de soucis ici, le code respecte bien le paradigme fonctionnel. Seulement, la variable volume n'a pas d’intérêt, on peut renvoyer directement le résultat...
# code n°6
def concatene(l1, l2):
return l1 + l2
print(concatene([1, 2], [3, 4]))
Attention ici le code de départ modifie la liste l1.
from random import random
def deplacement_smiley(pos: list)->list:
for i in range(len(pos)):
if random() > 0.3:
pos[i] += 1
return pos
def affichage_smiley(pos: list, smileys: list)->None:
for i in range(len(pos)):
print(smileys[i] * pos[i])
def une_seconde_de_course(pos: list, smile: list)->None:
affichage_smiley(pos,smile)
pos = deplacement_smiley(pos)
def course(pos: list, smileys:l ist, temps: int)->None:
while temps != 0:
temps = temps-1
print(temps)
une_seconde_de_course(pos, smileys)
secondes = 10
smileys=['\U0001F600', '\U0001F60A', '\U0001F643']
positions_smiley = [1, 1, 1]
course(positions_smiley, smileys, secondes)
from random import random
def f(a: int)->int:
'''
ATTENTION random : non fonctionnel ( pourquoi ? )
'''
r = random()
if r > 0.3:
return a + 1
else :
return a
def deplacement_smiley(pos: list)->list:
tab = list(map(f, pos))
return tab
def affichage_smiley(pos: list, smileys: list, seconde: int, i: int)->None:
'''
ATTENTION print : non fonctionnel
'''
if i == len(pos):
print(seconde)
else:
print (smileys[i] * pos[i])
return affichage_smiley(pos, smileys, seconde, i+1)
def une_seconde_de_course(pos: list, smileys: list, seconde: int, i: int)->list:
affichage_smiley(pos, smileys, seconde, i)
pos_suivante = deplacement_smiley(pos)
return pos_suivante
def course(pos: list, smileys: list, temps:int, i: int)->None:
pos = une_seconde_de_course(pos, smileys, temps, i)
if temps != 0:
course(pos, smileys, temps - 1, i)
secondes = 10
smile = ['\U0001F600','\U0001F60A','\U0001F643']
positions_smiley = [1, 1, 1]
i=0
course(positions_smiley, smile, secondes, i)