Syntaxes Python malines : le mémo express pour gagner du temps

Comme beaucoup de devs, j’ai tendance à oublier la syntaxe super utile pile au moment où j’en ai besoin. Alors, pour éviter les “attends, c’est comment déjà ce truc avec les compréhensions ?”, j’ai commencé à compiler une petite liste maison.

Et comme je suis sympa (et un peu fatigué de la chercher à chaque fois dans mes notes), je vous la partage ici. Un pense-bête Python plein de syntaxes futées, de raccourcis élégants, et de mini-astuces qui sauvent la mise.

Je compte bien la mettre à jour régulièrement – ou du moins chaque fois que je retombe sur une pépite oubliée.

Pour rendre tout ça digeste, j’ai rangé les syntaxes en quelques catégories :

  • Les itérables ou en plus long les structures de données à boucler (parce que tout est plus fun avec une boucle)
  • L’unpacking (ou comment déballer proprement son code)
  • Les compréhensions (magie noire de lisibilité en une ligne)

LES ITÉRABLES

Un itérable est ce qui accepte l’itération, ce sur quoi on peut itérer, c’est à dire une collection dont on peut prendre les éléments un à un.

Sam & Max

Le site de Sam & Max, souvent appelé “Sam et Max – Du code, du cul”, était un blog très populaire dans la communauté francophone du développement, particulièrement pour ses articles sur Python. Le site se distinguait par son ton décalé, ses billets techniques de grande qualité et son approche sans filtre, alternant entre sujets de programmation (principalement Python) et billets plus personnels ou humoristiques.

Création d’un itérable

On génère une séquence allant de 1 à 50 avec un incrément de 3 et on affiche le résultat :

seq = range(1, 50 3)
list(seq)
Python
[1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49]
Zsh

Calcul de la somme des éléments de l’itérable

On fait la somme de nos éléments contenus dans notre itérable seq.

sum(seq)
Python
425
Zsh

Appliquer un filtre sur une séquence

Utilise filter pour parcourir la séquence et ne conserver que les éléments qui respectent une condition (ici : être pair).

pair_condition = lambda i: i % 2==0
seq_filtered = filter(pair_condition, seq)
list(seq_filtered)
Python
[4, 10, 16, 22, 28, 34, 40, 46]
Zsh

Trouver si au moins un élément de l’itérable est pair

any(i % 2==0 for i in seq)
Python
True
Zsh

Trouver si tous les éléments de l’itérable sont pairs

all(i % 2==0 for i in seq)
Python
False
Zsh

Appliquer une fonction « Numpy »

Calcul de la somme cumulée des éléments de notre itérable

import numpy as np
list(np.cumsum(seq))
Python
[1, 5, 12, 22, 35, 51, 70, 92, 117, 145, 176, 210, 247, 287, 330, 376, 425]
Zsh

Récupérer le tuple (index, valeur) de l’itérable

Permet d’avoir les éléments tout en récupérant leur position (index).

t = list(enumerate(seq))
t
Python
[(0, 1),
(1, 4),
(2, 7), 
(3, 10),
 (4, 13),
 (5, 16),
 (6, 19),
 (7, 22),
 (8, 25),
 (9, 28),
 (10, 31),
 (11, 34),
 (12, 37),
 (13, 40),
 (14, 43),
 (15, 46),
 (16, 49)]
Zsh

Transposition de la liste de tuples

Autrement dit, on sépare les indices i et les valeurs de seq.

list(zip(*t))
Python
[(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16),
 (1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49)]
Zsh

Transformer une chaine de caractères en liste

s = "Le Machine Learning est quelque chose de nouveau sous le soleil : une technologie qui se construit elle-même."
l = s.split(' ')
l
Python
['Le',
 'Machine',
 'Learning',
 'est',
 'quelque',
 'chose',
 'de',
 'nouveau',
 'sous',
 'le',
 'soleil',
 ':',
 'une',
 'technologie',
 'qui',
 'se',
 'construit',
 'elle-même.']
Zsh

Transformer une liste en chaine de caractères

'_'.join(l)
Python
'Le_Machine_Learning_est_quelque_chose_de_nouveau_sous_le_soleil_:_une_technologie_qui_se_construit_elle-même.'
Zsh

Trier un itérable

On applique la fonction str.lower pour ne pas prendre en compte la casse.

ol = sorted(l, key=str.lower)
ol
Python
[':',
 'chose',
 'construit',
 'de',
 'elle-même.',
 'est',
 'Le',
 'le',
 'Learning',
 'Machine',
 'nouveau',
 'quelque',
 'qui',
 'se',
 'soleil',
 'sous',
 'technologie',
 'une']
Zsh

Si l’on souhaite avoir l’index de notre chaine de caractère associer à notre sous-chaine de caractère, nous pouvons utiliser la fonction enumarate() :

sorted(enumerate(l), key=lambda i: i[1].lower())
Python
[(11, ':'),
 (5, 'chose'),
 (16, 'construit'),
 (6, 'de'),
 (17, 'elle-même.'),
 (3, 'est'),
 (0, 'Le'),
 (9, 'le'),
 (2, 'Learning'),
 (1, 'Machine'),
 (7, 'nouveau'),
 (4, 'quelque'),
 (14, 'qui'),
 (15, 'se'),
 (10, 'soleil'),
 (8, 'sous'),
 (13, 'technologie'),
 (12, 'une')]
Zsh

Utilisation de l’opérateur *

Pour générer un itérable avec un même élément répété 10 fois

[1] * 10
Python
[1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
Zsh

Facilement créer un diviseur :

'-' * 20
Python
'--------------------'
Zsh

Convertir une liste de tuples en dictionnaire

dict(enumerate(l))
Python
{0: 'Le',
 1: 'Machine',
 2: 'Learning',
 3: 'est',
 4: 'quelque',
 5: 'chose',
 6: 'de',
 7: 'nouveau',
 8: 'sous',
 9: 'le',
 10: 'soleil',
 11: ':',
 12: 'une',
 13: 'technologie',
 14: 'qui',
 15: 'se',
 16: 'construit',
 17: 'elle-même.'}
Zsh

Fusionner deux dictionnaires

On créé trois dictionnaires : les deux premier que l’on souhaite fusionner et une dernière qui va contenir la fusion des deux dictionnaire. Ce dernier est initialisé comme une copie de notre premier dict avec la méthode .copy()

d1 = {"Arthur":1, "John":1}
d1_d2 = d1.copy()
d2 = {"Jason":2, "Kevin":5, "John":33}
Python

Enfin, on utilise la méthode .update() pour fusionner nos deux dictionnaires

d1_d2.update(d2)
d1_d2
Python
{'Arthur': 1, 'John': 33, 'Jason': 2, 'Kevin': 5}
Zsh

Autre syntaxe possible :

{**d1 , **d2}
Python
{'Arthur': 1, 'John': 33, 'Jason': 2, 'Kevin': 5}
Zsh

NB: Si des clés sont présentes dans les deux dictionnaires, c’est la valeur contenue dans le second dictionnaire qui sera conservée

Avec une addition des valeurs pour les clés identiques

Pour cela on peut importer Counter

from collections import Counter
dc1 = Counter(d1)
dc2 = Counter(d2)
dict(dc1 + dc2)
Python
{'Arthur': 1, 'John': 34, 'Jason': 2, 'Kevin': 5}
Zsh

Compter les occurrences des éléments d’un itérable

dict(Counter(['jaune', 'vert', 'vert']))
Python
{'jaune': 1, 'vert': 2}
Zsh

Autre exemple avec une chaine de caractère :

dict(Counter('Arthur'))
Python
{'A': 1, 'r': 2, 't': 1, 'h': 1, 'u': 1}
Zsh

Découper un itérable (slice)

Si on veut avoir une variable qui nous permet de récupérer le dernier élément d’un itérable, il nous suffit d’utiliser la fonction slice()

l = ['Le', 'Machine', 'Learning', 'est', 'quelque', 'chose', 'de', 'nouveau', 'sous', 'le', 'soleil', ':', 'une', 'technologie', 'qui', 'se', 'construit', 'elle-même.']
LAST_ELEMENT = slice(-1, None)
l[LAST_ELEMENT]
Python
['elle-même.']
Zsh

Se débarasser de caractères avant et après d’une chaine de caractères

text_balise = "[b]Ceci est un texte en gras[/b]"
left_strip = text_balise.lstrip('[/b]')
right_strip = text_balise.rstrip('[/b]')
text_strip = text_balise.strip('[/b]')
print(left_strip)
print(right_strip)
print(text_strip)
Python
'Ceci est un texte en gras[/b]'
'[b]Ceci est un texte en gras'
'Ceci est un texte en gras'
Zsh

Inverser l’ordre d’un itérable

text_strip[::-1]
Python
'sarg ne etxet nu tse iceC'
Zsh

Retourner toutes les permutations possibles

from itertools import permutations
perm = permutations([1, 2, 3])
list(perm)
Python
[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]
Zsh

Retourner toutes les combinaisons possibles

from itertools import combinations 
comb = combinations([1, 2, 3, 4, 5], 3)
list(comb)
Python
[(1, 2, 3),
 (1, 2, 4),
 (1, 2, 5),
 (1, 3, 4),
 (1, 3, 5),
 (1, 4, 5),
 (2, 3, 4),
 (2, 3, 5),
 (2, 4, 5),
 (3, 4, 5)]
Zsh

L’UNPACKING

Décomposition d’un itérable en variables

Attribue chaque élément de la liste à une variable correspondante, dans l’ordre.

a, b, c = [2, 5, 10]
a
Python
2
Zsh

Décomposition partielle d’un itérable en variables

a, *b = [2, 5, 10]
print(a)
print(b)
Python
2
[5, 10]
Zsh

Interchanger les valeurs des variables

Echangé deux variables sans variable temporaire.

a, b = b, a
a
Python
[5, 10]
Zsh

Ignorer certaines valeurs

Utilise _ comme joker pour ignorer les valeurs dont on ne veut pas.

a, _, c = [2, 5, 10]
print(a)
print(c)
Python
2
10
Zsh

LES COMPRÉHENSIONS

Utilisation des compréhensions de liste

Si on souhaite ajouter 3 à chaque élément de d’un itérable :

seq = [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49]
seq_plus_three = [i + 3 for i in seq]
seq_plus_three
Python
[4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49, 52]
Zsh

Création de listes avec condition

Crée une liste contenant uniquement les nombres pairs entre 0 et 9.

[i for i in range(10) if i % 2 == 0]
Python
[0, 2, 4, 6, 8]
Zsh

Utilisation des compréhensions de dictionnaire

Si on souhaite créer un dictionnaire de mapping entre un nombre et son carré :

xlist = [1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46, 49]
{i:i ** 2 for i in xlist}
Python
{1: 1,
 4: 16,
 7: 49,
 10: 100,
 13: 169,
 16: 256,
 19: 361,
 22: 484,
 25: 625,
 28: 784,
 31: 961,
 34: 1156,
 37: 1369,
 40: 1600,
 43: 1849,
 46: 2116,
 49: 2401}
Zsh

Création d’ensembles

Crée un ensemble à partir d’une liste — les doublons sont supprimés automatiquement.

{i for i in [1, 2, 1, 3]}
Python
{1, 2, 3}
Zsh