Vous avez un code qui marche, et vous voulez le rendre plus joli, plus lisible. C'est ce qu'on appelle du refactoring. Voici une liste de transformations disponibles pour vous aider dans cette tâche. Vous pouvez bien sûr choisir de faire la transformation ou non. Un "→" indique que ce code sera probablement plus clair (selon moi). Un "↔" indique que la clarté dépendra du contexte (il n'y en n'a pas un qui soit à priori plus clair).
if CONDITION:
A
else:
B
# ↔
if not(CONDITION):
B
else:
A
if a == 5:
print("hello")
else:
waw = 2
# ↔ (inverser if/else)
if not(a == 5):
waw = 2
else:
print("hello")
# ↔ (not == ↔ !=)
if a != 5:
waw = 2
else:
print("hello")
if CONDITION:
A
else:
pass # ne rien faire
# →
if CONDITION:
A
if a != 5:
print("hello")
else:
pass # ne rien faire
# → ("sinon ne rien faire" est inutile)
if a != 5:
print("hello")
if a == 5:
pass # ne rien faire
else:
print("hello")
# → (inverser if/else)
if a != 5:
print("hello")
else:
pass # ne rien faire
# → ("sinon ne rien faire" est inutile)
if a != 5:
print("hello")
# De Morgan sur "et"
if not(A and B):
...
# ↔
if (not A) or (not B):
...
# De Morgan sur "ou"
if not(A or B):
...
# ↔
if (not A) and (not B):
...
if not(a > 10 or a == 5):
print('hello')
# → (De Morgan)
if a <= 10 and a != 5:
print('hello')
if a > 10 or a == 5:
pass
else:
print('hello')
# → (inverser if/else)
if not(a > 10 or a == 5):
print('hello')
else:
pass
# → ("sinon ne rien faire" est inutile)
if not(a > 10 or a == 5):
print('hello')
# → (De Morgan)
if a <= 10 and a != 5:
print('hello')
if a < b:
print("hello")
if a >= b:
print("tada")
# → (à condition que a et b ne soient pas modifiés dans le if !)
if a < b:
print("hello")
else:
print("tada")
if CONDITION:
x = A
else:
x = B
# →
x = A if CONDITION else B
# →
x = (A if CONDITION else B)
# →
x = (A if CONDITION else
B)
if a == 5:
c = 2
else:
c = 0
# → ("if en une ligne" aussi appelé "l'opérateur ternaire" ou le "if fonctionnel")
c = (5 if a == 5 else 0)
# ↔ (parenthèses non nécessaires)
c = 5 if a == 5 else 0
if CONDITION:
x = A
elif CONDITION_2:
x = B
elif CONDITION_3:
x = C
else:
x = D
# →
x = (A if CONDITION else
B if CONDITION_2 else
C if CONDITION_3 else
D)
if a == 5:
c = 8
elif a == 2:
c = 4
elif a < 0:
c = 1
else:
c = 0
# → (if fonctionnel)
c = (8 if a == 5 else
4 if a == 2 else
1 if a < 0 else
0)
Vous pouvez renommer une variable pour lui donner un nom plus explicite :
e = v * t
i = e / 2.56
# →
distance = vitesse * temps
distance_pouces = distance / 2.56
Généralement les noms de variables de quelques lettres sont trop court (sauf dans des expressions mathématiques ou des noms de variables connues comme le "i"
dans une boucle) et des variables avec plus de trois vrais mots ont un nom trop long (un commentaire à la création de la variable sera sûrement plus clair).
x = ...
operation(x)
# → (à condition que x n'est utilisé qu'une fois)
operation(...)
x = taille + 1 # x dépend de la taille
y = taille - 1 # y dépend de la taille
le_coefficent = x + 2 * y # on calcule le coefficent avec la formule linéaire
print(le_coefficent) # on l'affiche
# ↔ (inline variable "le_coefficent")
x = taille + 1 # x dépend de la taille
y = taille - 1 # y dépend de la taille
print(x + 2 * y) # on affiche le résultat de la formule linéaire
# ↔ (inline variables "x" and "y")
print((taille + 1) + 2 * (taille - 1)) # on affiche le résultat de la formule linéaire en fonction de la taille
def f(...):
...
if CONDITION:
return True
else:
return False
# →
def f(...):
...
return CONDITION
if CONDITION:
res = True
else:
res = False
# →
res = CONDITION
def est_pair(x):
if x % 2 == 0: # si le reste de la division par deux vaut 0
return True # Vrai, le nombre est pair
else: # sinon
return False # Faux, le nombre n'est pas pair
# → (boolean return)
def est_pair(x):
return x % 2 == 0 # x est pair ssi le reste de la division par deux vaut 0
# :
if est_pair(4):
...
if x % 2 == 0: # si le reste de la division par deux vaut 0
res = True # le résultat est Vrai, le nombre est pair
else: # sinon
res = False # le résultat est Faux, le nombre n'est pas pair
# → (boolean return)
res = (x % 2 == 0) # le résultat est vrai ssi le reste de la division par deux vaut 0
# → (renaming)
est_pair = (x % 2 == 0) # on nomme la variable de manière sémantique
# ↔ (parenthesis)
est_pair = x % 2 == 0 # parenthèses non nécessaires
def voyelle(x):
if x == 'a' or x == 'e' or x == 'i' or x == 'o' or x == 'u':
return True
else:
return False
# → (boolean return)
def voyelle(x):
return x == 'a' or x == 'e' or x == 'i' or x == 'o' or x == 'u' # x est une voyelle ssi x vaut 'a', 'e', 'i', 'o', ou 'u'
# :
if voyelle('a'): # si 'a' est une voyelle
...
# avec
def est_pair(x):
if x % 2 == 0: # si le reste de la division par deux vaut 0
return True
else:
return False
# :
if est_pair(4) == True: # si la fonction est_pair renvoie True
...
# →
if est_pair(4): # si 4 est pair
...
if CONDITION:
A
elif CONDITION_2:
A # même A
# →
if CONDITION or CONDITION_2:
A
if a == 5:
x = 2
elif a > 10:
x = 2
# → (or)
if a == 5 or a > 10:
x = 2
if CONDITION:
A
elif CONDITION_2:
A # même A
else:
B
# →
if CONDITION or CONDITION_2:
A
else:
B
if a == 5:
x = 2
elif a > 10:
x = 2
else:
print('error')
# → (or)
if a == 5 or a > 10:
x = 2
else:
print('error')
def f(...):
...
if CONDITION:
return True
if CONDITION_2:
return True
return False
# →
def f(...):
...
return CONDITION or CONDITION_2
# ↔
def f(...):
...
return (CONDITION
or CONDITION_2)
def interessant(x):
if x > 10: # si x > 10
return True # il est intéressant
if x == 5: # si x == 5
return True # il est intéressant
return False # sinon, il n'est pas intéressant
# → (or return)
def interessant(x):
return x > 10 or x == 5 # x est intéressant si il est > 10 ou == 5
if CONDITION:
if CONDITION_2:
A
# →
if CONDITION and CONDITION_2:
A
if a == 5:
if a > 10:
print('waw')
# → (and)
if a == 5 and a > 10:
print('waw')
if CONDITION:
if CONDITION_2:
A
else:
B
else:
B # même b
# →
if CONDITION and CONDITION_2:
A
else:
B
if a == 5:
if b > 10:
waw = 2
else:
print('error')
else:
print('error')
# → (and)
if a == 5 and b > 10:
waw = 2
else:
print('error')
def f(...):
...
if CONDITION:
return X
...
# ↔
def f(...):
...
if CONDITION:
return X
else:
...
def f(x):
if x < 0:
return -1
else:
y = x + 2
z = y ** 2
return z
# → (if return)
def f(x):
if x < 0:
return -1
y = x + 2
z = y ** 2
return z
Je fais généralement ça quand le "if"
est vraiment court comme un simple "return"
. Souvent, ce sont des cas particuliers ou des cas de base, le code du bas est plus intéressant.
# Voici comment on code un "∃"
def f(...):
...
for x in L:
if condition: # ce "if" n'a PAS de "else"
return True
return False
# → (en python, il y a "all")
def f(...):
...
return any(condition for x in L)
# ↔
def f(...):
...
return any(condition
for x in L)
# Note: en python, il y a aussi le for...else mais peu de gens l'utilisent
def contient_un_negatif(L):
for x in L: # pour tous les élements de la liste
if x < 0: # s'il est < 0
return True # la liste contient_un_negatif
return False # au final, c'est qu'elle n'en contient pas
# → (any)
def contient_un_negatif(L):
return any(x < 0 for x in L)
Qui se lira Une liste L contient un négatif si...
# Voici comment on code un "∀"
def f(...):
...
for x in L:
if condition: # ce if n'a PAS de "else"
return False
return True
# → (en python, il y a "all")
def f(...):
return all(not condition for x in L)
# ↔
def f(...):
return all(not condition
for x in L)
# Note: en python, il y a aussi le for...else mais peu de gens l'utilisent
def totalement_positive(L):
for x in L: # pour tous les élements de la liste
if x < 0: # s'il est < 0
return False # la liste n'est pas totalement_positive
return True # au final, c'est que la liste est totalement_positive
# → (all)
def totalement_positive(L):
return all(x >= 0 for x in L)
Qui se lira Une liste L est totalement_positive si...
# De Morgan sur "∀"
not all(condition for x in L)
# →
any(not condition for x in L)
# De Morgan sur "∃"
not any(condition for x in L)
# →
all(not condition for x in L)
if not all(x >= 0 for x in L): # si on n'a pas tous les nombres >= 0
...
# → (if non empty)
if any(x < 0 for x in L): # c'est qu'il existe un nombre < 0
...
Attention: cette transformation ne marche pas si L est vide !
# Voici comment on code une recherche linéaire
def f(...):
for x in L:
if condition:
return a
return b
# → (en python, il y a "next")
def f(...):
return next((a for x in L if condition), b)
# ↔
def f(...):
return next((a for x in L if condition),
b)
# Note: en python, il y a aussi le for...else mais peu de gens l'utilisent
Le super_nombre d'une liste est le premier x dans la liste tel que x > 10 :
def super_nombre(L):
for x in L: # pour tous les élements de la liste
if x > 10: # s'il est > 10
return x # c'est le super nombre de cette liste
return 0 # il n'y a pas de super nombre, on renvoie 0
# →
def super_nombre(L):
return next((x for x in L if x > 10), 0)
L = []
for x in iterable:
L.append(e)
# →
L = [e for x in iterable]
L = []
for x in iterable:
L.append(f(x))
# →
L = list(map(f, iterable))
# ↔
L = [f(x) for x in iterable]
L = []
for x in iterable:
if condition:
L.append(e)
# →
L = [e for x in iterable if condition]
L = []
for x in iterable:
if f(x):
L.append(x)
# →
L = list(filter(f, iterable))
# ↔
L = [x for x in iterable if f(x)]
for x in list(generateur):
...
# →
for x in generateur:
...
for x in list(map(f, L)): # map, filter, zip...
...
# →
for x in map(f, L):
...
# avec
def operation(x):
return (x + 1) * 2 - x
# :
for x in list(map(operation, [1,2,3])):
print(x)
# →
for x in map(operation, [1,2,3]):
print(x)
s = 0
for x in L:
s += a
# → (sum)
s = sum(a for x in L)
# techniquement, "sum" est un cas particulier de "reduce" mais "reduce" est peu utile en python
s = ''
for x in L:
s += a
# → (join)
s = ''.join(a for x in L)
# techniquement, "join" est un cas particulier de "reduce" mais "reduce" est peu utile en python
if x == 'a' or x == 'e' or x == 'i' or x == 'o' or x == 'u':
...
# → (in)
if x in ('a', 'e', 'i', 'o', 'u'):
...
# c'est un cas particulier de recherche linéaire dans une liste