Sommaire
Python ne se sert pas de points-virgules pour délimiter les instructions. À la place, l'indentation et les espaces structurent le code.
if instruction:
instruction
Lorsqu'une instruction est trop longue, Python permet de la répartir sur plusieurs lignes en utilisant le caractère de continuation \.
Les commentaires sur une ligne, commencent par le symbole #.
Les blocs de commentaires s'effectuent via le symbole """ ou '''.
# Ceci est un commentaire sur une seule ligne
x = 5 # Ce commentaire explique que x est assigné à 5
x = 5 """ Ce commentaire explique que x est assigné à 5 """
"""
Ceci est un commentaire sur plusieurs lignes
utilisant une chaîne de caractères multilignes.
Il est souvent utilisé pour des blocs de texte plus longs.
"""
# DOCSTRINGS
def addition(a, b):
"""
Cette fonction prend deux nombres et retourne leur somme.
:param a: Le premier nombre
:param b: Le deuxième nombre
:return: La somme de a et b
"""
return a + b
Pour déterminer le nom des variables, fonctions, classe, modules, on va les écrire en camel_case. Python est sensible à la casse.
Pour avoir la liste complète des mots clés:
import keyword
print(keyword.kwlist)
L'esprit "pythonic" :
Le Slicing permet d'extraire facilement une sous-séquence d'une liste, d'un tuple ou d'une chaîne de caractères grâce à une syntaxe intuitive (par exemple, liste[1:4] pour obtenir les éléments d'index 1 à 3). Cela favorise une écriture de code à la fois concise et expressive, permettant de manipuler les séquences sans boucles complexes.
L'unpacking consiste à décomposer une séquence ou un itérable en plusieurs variables en une seule ligne (comme: a, b, c = [1, 2, 3]). Cette fonctionnalité offre une approche élégante pour assigner des valeurs à plusieurs variables, tout en permettant des extractions partielles grâce à l'opérateur * (par exemple:, a, *middle, c = [1, 2, 3, 4, 5]).
Pour former une chaîne de caractère on peut utiliser l'apostrophe (') ou les guillemets (").
On peut également utiliser des 'triple' apostrophes: ''', ce qui permet d'écrire une chaîne de caractère sur plusieurs lignes:
ma_super_chaine = '''
Bienvenue
Tout le monde !
\o/
'''
Le caractère d'échappement est: \.
Si on ne souhaite pas qu'il soit interpréter on doit ajouter la lettre 'r' devant la chaîne de caractère:
r'C:\tmp\mon\repertoire'
Pour ajouter un variable à une chaîne de caractère, on utilise la lettre 'f' et les accolades {}:
name = 'John'
msg = f"Bonjour {name}"
name = 'John'
msg = f"Bonjour {name}"
Pour concaténer on va utiliser le caractère +.
A savoir, on peut concaténer deux chaînes de caractères entre elles en les séparant par un espace:
msg = 'Bonjour ' 'le monde!'
En Python une chaîne vide est évalué à False.
Dans cette section nous alors voir les opérations possibles sur une chaîne de caractères.
msg = 'Hello World'
print(str[0]) # H
print(str[1]) # e
print(str[-1]) # d
print(str[-2]) # l
Utiliser la fonction len()
msg = 'Hello World'
msg_len = len(msg)
print(msg_len) # 11
Quelques chose de très sexy ici pour extraire une portion d'une chaîne, le slicing.
string[start:end].
Ici, start et end ne sont pas obligatoire. Ainsi, on peut retirer une portion à gauche ou à droite de la chaîne.
text = "Bonjour le monde"
# Extrait les caractères de l'indice 3 à 9
print(text[3:9]) # Sortie : "jour l"
# Extrait les caractères de l'indice 0 à 7 avec un pas de 2
print(text[0:7:2]) # Sortie : "Bnj"
# Inverse la chaîne
print(text[::-1]) # Sortie : "ednom el ruojnoB"
Remarque: le slicing fonctionne aussi sur les listes, les tuples et autres objets supportant l'indexation. Un vrai délice!
Les chaînes de caractères sont immuables
Si vous souhaitez modifier une chaîne de caractères, il faut en créer une nouvelle.
Il s'agit ici de notions plus "avancée", je conseil de suivre le cour L'Algorithmique si vous n'êtes pas à l'aise avec les boucles et les fonctions anonymes.
Je considère qu'il est important de connaître les différentes fonctionnalités offertes par le langage concernant les chaînes de caractères. Vous pouvez passer cette partie pour l'instant et y revenir ultérieurement si besoin.
La fonction map() est généralement utilisée avec des itérables comme des listes ou des tuples. Une chaîne de caractères (str) est aussi un itérable en Python (chaque caractère peut être parcouru).
Ci-après quelques exemples d'utilisation de map() sur une chaîne de caractère.
Transformer chaque caractère en majuscule:
text = "Bonjour le monde"
# Utilisation de map() pour convertir chaque caractère en majuscule
resultat = map(str.upper, text)
# Conversion en liste puis en chaîne de caractères
print("".join(resultat)) # Affiche : "BONJOUR LE MONDE"
Explication:
str.upper est appliqué à chaque caractère.map est transformé en une liste de caractères, puis joint avec "".join() pour reformer une chaîne.Remplacer les espaces par un tiret (-):
text = "Bonjour le monde"
# Remplacer chaque espace par un tiret
resultat = map(lambda c: "-" if c == " " else c, text)
print("".join(resultat)) # Affiche : "Bonjour-le-monde"
Explication : La fonction lambda remplace les espaces par -, sinon elle garde le caractère d'origine.
Obtenir les codes ASCII de chaque caractère:
text = "Bonjour"
# Utilisation de map() pour obtenir le code ASCII de chaque caractère
resultat = map(ord, text)
print(list(resultat))
# Affiche : [66, 111, 110, 106, 111, 117, 114] (Codes ASCII des lettres de "Bonjour")
Explication : ord(c) renvoie le code ASCII du caractère c.
Il s'agit ici de notions plus "avancée", je conseil de suivre le cour L'Algorithmique si vous n'êtes pas à l'aise avec les boucles et les fonctions anonymes.
Je considère qu'il est important de connaître les différentes fonctionnalités offertes par le langage concernant les chaînes de caractères. Vous pouvez passer cette partie pour l'instant et y revenir ultérieurement si besoin.
filter() permet de filtrer un itérable en ne retenant que les éléments qui satisfont une condition.
Voici un exemple avec une chaîne de caractères, extraire uniquement les lettres majuscules:
texte = "Hello World! Bienvenue sur Python."
# La fonction lambda vérifie si le caractère est une majuscule
majuscules = filter(lambda c: c.isupper(), texte)
# Reconstituer la chaîne filtrée
resultat = "".join(majuscules)
print(resultat) # Affiche : "HWBP"
Explication: La méthode isupper() renvoie True pour les lettres majuscules. Ici, filter() parcourt la chaîne caractère par caractère.
Il s'agit ici de notions plus "avancée", je conseil de suivre le cour L'Algorithmique si vous n'êtes pas à l'aise avec les boucles et les fonctions anonymes. Notamment la section à propos de reduce().
Je considère qu'il est important de connaître les différentes fonctionnalités offertes par le langage concernant les chaînes de caractères. Vous pouvez passer cette partie pour l'instant et y revenir ultérieurement si besoin.
reduce() peut-être utilisé sur une chaîne de caractères. Le principe: on indique une fonction qui est d'abord appliquée aux deux premiers éléments de l'itérable, puis le résultat est combiné avec le troisième élément, et ainsi de suite jusqu'à obtenir une valeur finale.
# Concaténation de chaînes de caractères
from functools import reduce
mots = ["Bonjour", "le", "monde"]
phrase = reduce(lambda x, y: x + " " + y, mots)
print(phrase) # Affiche : "Bonjour le monde"
Ici, la fonction lambda concatène deux chaînes en insérant un espace entre elles.
Il s'agit ici de notions plus "avancée", je conseil de suivre le cour L'Algorithmique si vous n'êtes pas à l'aise avec les boucles.
Je considère qu'il est important de connaître les différentes fonctionnalités offertes par le langage concernant les chaînes de caractères. Vous pouvez passer cette partie pour l'instant et y revenir ultérieurement si besoin.
Trier une chaîne via sorted()
chaine = "python"
resultat = sorted(chaine)
print(resultat) # Affiche : ['h', 'n', 'o', 'p', 't', 'y']
# Pour reconstituer une chaîne triée :
chaine_triee = "".join(sorted(chaine))
print(chaine_triee) # Affiche : "hnopty"
Pour les fondamentaux, on ne parle ici que des int et float.
Rien de particulier ici, le float est dominant.
Python supporte les underscores dans les nombres:
count = 10_000_000_000
print(count) # 10000000000
Rien de particulier, il faut respecter la casse ainsi on assigne un booléen avec le valeur suivante: True ou False.
Si on souhaites savoir si une valeurs est vraie ou fausse, on dispose de la fonction bool().
Ce n'est pas supporté dans Python, la convention est de créer une variable et de l'écrire en majuscule pour indiquer qu'il s'agit d'une constante:
FILE_SIZE_LIMIT = 2000
Python est comme le Php faiblement typé, mais typé tout de même.
Ainsi, nous disposons de fonctions de "transtypage": int(str), float(str), bool(val), str(val).
Pour avoir le type d'une variable, on dispose de la fonction type().
Remarque personnel:
Priorité à la compréhension du langage: Avant de se plonger dans les annotations de type, il est essentiel de bien comprendre les bases de Python : syntaxe, structures de contrôle, fonctions, classes, etc. Les annotations de type sont un outil supplémentaire qui peut être introduit une fois que vous êtes à l'aise avec le langage.
Venant de php, j'ai cherché à "typer" assez rapidement, c'est pourquoi je place cette section ici.
Python est réputé pour sa syntaxe claire et son approche dynamique. Cela signifie que les variables ne sont pas déclarées avec un type fixe; ce qui importe, c'est le comportement des objets à l'exécution (principe du duck typing). Cependant, Python reste fortement typé : il interdit par exemple l'addition d'un nombre et d'une chaîne de caractères sans conversion explicite.
Les annotations de type (Type Hints) permettent de:
Le système de typage en Python est graduel : vous pouvez ajouter des annotations à mesure que votre projet évolue, sans devoir les imposer partout ni modifier le comportement du runtime. Vous bénéficiez ainsi d'un compromis entre souplesse et sécurité.
L'annotation se fait en plaçant un deux-points après le nom de la variable suivi de son type (et éventuellement une valeur) :
# Exemple simple
nom_programme: str = "Python"
version: float = 3.10
est_actif: bool = True
Même si ces annotations servent de documentation et d'aide statique, Python ne les impose pas à l'exécution. Vous pouvez par exemple écrire :
texte: str = "Bonjour"
texte = 42 # Python acceptera ceci, mais un outil statique comme mypy le signalera.
print(texte)
Pour annoter une fonction, on précise après le nom de chaque paramètre son type et, après le symbole ->, le type de retour:
def saluer(nom: str) -> str:
return f"Bonjour {nom} !"
# Exemple d'utilisation :
message = saluer("Alice")
print(message) # Affiche: Bonjour Alice !
Si la fonction ne renvoie rien, le type de retour est None:
def afficher(message: str) -> None:
print(message)
Les structures de données sont étudiées un peu plus loin, voici ici comment appliquer le Type Hints sur ces derniers.
Les Type Hints permettent de décrire le contenu des collections :
# Liste d'entiers
nombres: list[int] = [1, 2, 3, 4]
# Dictionnaire avec des chaînes comme clés et des flottants comme valeurs
poids: dict[str, float] = {"pomme": 0.35, "banane": 0.22}
# Tuple fixe (int, str, float)
personne: tuple[int, str, float] = (1, "Alice", 3.14)
Union: permet de dire qu'une variable peut être de plusieurs types, via l'opérateur |.
def traiter(valeur: int | str) -> None:
print(valeur)
Optional: c'est en fait une Union avec None: à X | None).
def trouver_utilisateur(id: int) -> str | None:
# Retourne une chaîne si l'utilisateur est trouvé, sinon None
...
Les types génériques permettent d'écrire des fonctions ou classes qui fonctionnent avec plusieurs types tout en gardant la cohérence des annotations:
from typing import TypeVar, Generic
T = TypeVar('T')
def premier_element(liste: list[T]) -> T:
return liste[0]
# Exemple d'utilisation :
print(premier_element([1, 2, 3])) # Affiche 1
print(premier_element(["a", "b", "c"])) # Affiche "a"
Explications:
TypeVar est utilisé pour créer une variable de type. ici, T = TypeVar('T') crée une variable de type nommée T.'T' passé en paramètre à TypeVar est simplement une chaîne de caractères qui sert de nom pour cette variable de type. Vous pouvez utiliser n'importe quel nom, mais T est une convention courante pour indiquer un type générique.T peut être remplacé par n'importe quel type concret lorsque la fonction est appelée. Cela signifie que T peut être un int, un str, une list, ou tout autre type.Les Literal Types (introduits par la PEP 586) vous permettent de restreindre la valeur d'une variable à un ensemble précis de valeurs littérales. Par exemple, vous pouvez indiquer qu'une fonction n'accepte qu'une chaîne de caractères ayant exactement une valeur déterminée, ce qui renforce la précision de vos annotations. Un exemple simple:
from typing import Literal
def set_mode(mode: Literal['rouge', 'vert', 'bleu']) -> None:
print(f"Mode défini sur {mode}")
set_mode('rouge') # OK
# set_mode('jaune') # Ceci sera signalé par un vérificateur statique comme mypy.
Ce type d'annotation est très utile pour décrire des paramètres qui ne doivent prendre qu'un ensemble limité de valeurs prédéfinies.
Introduit dans la PEP 591, le mot-clé final permet d'indiquer qu'une variable, une méthode ou une classe ne doit pas être modifiée ou redéfinie par la suite. Cela sert principalement de documentation pour les développeurs et d'aide aux outils de vérification statique, puisqu'à l'exécution, Python n'impose pas ces contraintes. Par exemple:
from typing import final
@final
class Base:
def méthode(self) -> None:
print("Méthode dans Base")
# Toute tentative de sous-classement de Base sera signalée par un vérificateur de types.
class Fille(Base): # Erreur détectée par mypy ou pyright
def méthode(self) -> None:
print("Redéfinition dans Fille")
Ici, l'utilisation de final montre clairement que la classe Base (ou une méthode décorée avec final) n'est pas destinée à être étendue ou redéfinie.
NewType pour distinguer des types apparentésLorsqu'une valeur de base doit être considérée comme un type distinct (par exemple pour éviter les confusions entre identifiants), NewType permet de créer un alias fortement typé:
from typing import NewType
UserId = NewType('UserId', int)
def get_user_name(user_id: UserId) -> str:
# Traitement pour récupérer le nom d'un utilisateur
...
user = get_user_name(UserId(1001))
La POO sera abordée plus loin, mais voici comment utiliser le Type Hints avec les classes.
Les Type Hints s'appliquent également aux attributs et méthodes des classes. Elles aident à documenter l'interface d'un objet.
class Personne:
nom: str # Annotation de l'attribut
def __init__(self, nom: str) -> None:
self.nom = nom
def saluer(self) -> str:
return f"Bonjour, {self.nom} !"
# Utilisation :
p = Personne("Alice")
print(p.saluer()) # Affiche: Bonjour, Alice !
Pour des classes de données, vous pouvez également utiliser le décorateur @dataclass qui simplifie l'écriture en générant automatiquement l'init, le repr, etc., tout en permettant les annotations de type.
Les annotations de type présentent de nombreux bénéfices, notamment:
Mypy est un outil de vérification statique qui lit les annotations de type et signale les incohérences.
Il est nécessaire de l'installer: pip install mypy
Il s'utilise via le mot clé mypy: mypy mon_script.py
Si vous avez une fonction annotée mais qu'un type incorrect est passé, mypy vous l'indiquera avant l'exécution
Pyright est une "alternative" très rapide, souvent intégrée dans des éditeurs comme VS Code, qui réalise lui-même une vérification statique des types.
Il est recommandé d'ajouter des annotations progressivement, en commençant par les parties critiques du code, par exemple les interfaces publiques et les fonctions clés.
Pour les librairies ou les modules à usage externe, spécifiez clairement le contrat de vos fonctions (paramètres et retours) pour aider les utilisateurs.
AnyL'usage abusif de Any réduit les avantages du typage statique; mieux vaut être précis pour capter d'éventuelles erreurs.
La notion de Protocol (introduite dans la PEP 544) permet de définir des contrats de type basés sur le comportement (duck typing). Cela est particulièrement utile lorsque vous souhaitez définir des interfaces « non contraignantes » sans forcer une hiérarchie d'héritage.
from typing import Protocol
class Duck(Protocol):
def quack(self) -> str: ...
def nager(self) -> None: ...
class VraieCanard:
def quack(self) -> str:
return "Quack!"
def nager(self) -> None:
print("Je nage!")
def faire_nager(oiseau: Duck) -> None:
oiseau.nager()
faire_nager(VraieCanard()) # Valide même si VraieCanard n'hérite pas explicitement de Duck
Pour que isinstance puisse fonctionner avec un Protocol, pensez à utiliser le décorateur @runtime_checkable si nécessaire.
Bien que très utile, le système de Type Hints présente quelques limites :
Remarque: il existe d'autres types de variables comme les structures de données, elles sont passées en revue dans un autre chapitre.