Éliminer les boucles

Rédiger du code Python efficace

Logan Thomas

Scientific Software Technical Trainer, Enthought

Boucler en Python

  • Modèles de boucles :
    • boucle for : parcourir une séquence élément par élément
    • boucle while : répéter tant que la condition est vraie
    • boucles « imbriquées » : une boucle à l'intérieur d'une autre
    • Coûteux !
Rédiger du code Python efficace

Avantages d'éliminer les boucles

  • Moins de lignes de code
  • Lisibilité accrue
    • « Plat vaut mieux qu'imbriqué »
  • Gains d'efficacité
Rédiger du code Python efficace

Éliminer les boucles avec les fonctions intégrées

# Liste de HP, Attack, Defense, Speed
poke_stats = [
    [90,  92, 75, 60],
    [25,  20, 15, 90],
    [65, 130, 60, 75],
    ...
]

alt="Les Pokémon nommés Abomasnow, Abra et Absol et leurs valeurs de points de vie, d'attaque, de défense et de vitesse mises en évidence"

Rédiger du code Python efficace
# Liste de HP, Attack, Defense, Speed
poke_stats = [
    [90,  92, 75, 60],
    [25,  20, 15, 90],
    [65, 130, 60, 75],
    ...
]

# Approche avec boucle for totals = [] for row in poke_stats: totals.append(sum(row))
# Compréhension de liste totals_comp = [sum(row) for row in poke_stats]
# Fonction intégrée map() totals_map = [*map(sum, poke_stats)]
Rédiger du code Python efficace
%%timeit
totals = []
for row in poke_stats:
    totals.append(sum(row))
140 µs ± 1.94 µs par boucle (moyenne ± éc. type de 7 exécutions, 10000 boucles chacune)
%timeit totals_comp = [sum(row) for row in poke_stats]
114 µs ± 3.55 µs par boucle (moyenne ± éc. type de 7 exécutions, 10000 boucles chacune)
%timeit totals_map = [*map(sum, poke_stats)]
95 µs ± 2.94 µs par boucle (moyenne ± éc. type de 7 exécutions, 10000 boucles chacune)
Rédiger du code Python efficace

Éliminer les boucles avec des modules intégrés

poke_types = ['Bug', 'Fire', 'Ghost', 'Grass', 'Water']
# Approche avec boucles for imbriquées
combos = []
for x in poke_types:
    for y in poke_types:
        if x == y:
            continue
        if ((x,y) not in combos) & ((y,x) not in combos):
            combos.append((x,y))
# Approche avec module intégré
from itertools import combinations
combos2 = [*combinations(poke_types, 2)]
Rédiger du code Python efficace

Éliminer les boucles avec NumPy

# Tableau de HP, Attack, Defense, Speed
import numpy as np

poke_stats = np.array([
    [90,  92, 75, 60],
    [25,  20, 15, 90],
    [65, 130, 60, 75],
    ...
])
Rédiger du code Python efficace

Éliminer les boucles avec NumPy

avgs = []
for row in poke_stats:
    avg = np.mean(row)
    avgs.append(avg)

print(avgs)
[79.25, 37.5, 82.5, ...]
avgs_np = poke_stats.mean(axis=1)

print(avgs_np)
[ 79.25  37.5   82.5  ...]
Rédiger du code Python efficace

Éliminer les boucles avec NumPy

%timeit avgs = poke_stats.mean(axis=1)
23.1 µs ± 235 ns par boucle (moyenne ± éc. type de 7 exécutions, 10000 boucles chacune)
%%timeit
avgs = []
for row in poke_stats:
    avg = np.mean(row)
    avgs.append(avg)
5.54 ms ± 224 µs par boucle (moyenne ± éc. type de 7 exécutions, 100 boucles chacune)
Rédiger du code Python efficace

Passons à la pratique !

Rédiger du code Python efficace

Preparing Video For Download...