Bonjour

je viens de lire cet article "les anti-patterns en python"

Bad
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
l = [1, 2, 3, 4] 
if 4 in l: 
  print("The number 4 is in the list.") 
else: 
  print("The number 4 is NOT in the list.")
Good
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
s = {1, 2, 3, 4}
if 4 in s: 
  print("The number 4 is in the list.") 
else: 
  print("The number 4 is NOT in the list.")
Puisque je ne fais jamais de if id in set(ma_liste): je me suis demandé si cela était vraiement un anti-pattern et surtout si cette optimisation était si bonne que l'on pouvais parler d"anti-pattern"

Mon petit test :
- liste longue / liste courte
- elements str / int
- item à trouver en fin ou début de liste (oui, cela compte )

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import timeit
 
tests = (
    (10000, lambda x: x),
    (10000, lambda x: str(x)),
    (100, lambda x: x),
    (100, lambda x: str(x)),
    (10, lambda x: x),
    (10, lambda x: str(x)),
    )
 
def get_by_list(id, conteneur):
    if id in conteneur:
        return True
    return False
 
def resultats(time_list, time_set, liste, find):
    msg = f'recherche "{find}" sur "{len(liste)}" items {type(liste[0])}'
    calcul = time_list / time_set
    print("\033[1;30;40mlist:", time_list)
    print("set :", time_set, "\033[0m")
    print(f"-> {calcul:.1f} fois plus rapide {msg}")
 
 
for test in tests:
    # liste = tuple(test[1](x) for x in range(test[0]))
    liste = [test[1](x) for x in range(test[0])]
    liste_set = set(liste)
 
    find = str((len(liste)//100)+2)
    time_list = timeit.timeit(lambda: get_by_list(find, liste), number=1000)
    time_set = timeit.timeit(lambda: get_by_list(find, liste_set), number=1000)
    resultats(time_list, time_set, liste, find)
 
    find = str(len(liste)-len(liste)//10)
    time_list = timeit.timeit(lambda: get_by_list(find, liste), number=1000)
    time_set = timeit.timeit(lambda: get_by_list(find, liste_set), number=1000)
    resultats(time_list, time_set, liste, find)
    print()
resultat... IL FAUT TESTER

sur une "petite" liste, ok il y a un gain de 2x, mais avec des valeurs si petites que j'ai du mal à parler d'anti-pattern et même d'optimisation
Pour une grande liste, ok la différence est claire

ps: dans son exemple, il écrit l = [1, 2, 3, 4] et moi, par défaut je fais toujours par défaut un tuple ... donc il illustre un antipattern avec un anti-pattern (du même type) ?
J'ai donc refait le test avec un tuple à la place de la liste, pas de différence avec la liste