Article: Guide Complet de Programmation Python pour Débutants

Article: Guide Complet de Programmation Python pour Débutants

Guide Complet de Programmation Python pour Débutants

Table des matières

  1. Introduction à Python
  2. Installation et configuration
  3. Les bases de Python
  4. Variables et types de données
  5. Opérateurs en Python
  6. Structures de contrôle
  7. Fonctions
  8. Structures de données
  9. Modules et packages
  10. Gestion des fichiers
  11. Gestion des exceptions
  12. Programmation orientée objet
  13. Bibliothèques standard
  14. Projets pratiques
  15. Bonnes pratiques
  16. Ressources complémentaires

Introduction à Python

Python est un langage de programmation polyvalent, puissant et pourtant facile à apprendre, créé par Guido van Rossum et publié pour la première fois en 1991. Considéré comme l'un des langages les plus accessibles pour les débutants, Python combine une syntaxe claire et lisible avec une grande flexibilité, ce qui en fait un choix idéal pour commencer votre voyage dans le monde de la programmation.

Pourquoi apprendre Python ?

Python présente de nombreux avantages qui expliquent sa popularité croissante :

  • Simplicité : Sa syntaxe proche du langage naturel facilite l'apprentissage et la lecture.
  • Polyvalence : Python s'utilise dans divers domaines tels que le développement web, la science des données, l'intelligence artificielle, l'automatisation, etc.
  • Grande communauté : Une vaste communauté de développeurs signifie une abondance de ressources, bibliothèques et assistance.
  • Demande professionnelle : Les compétences en Python sont très recherchées sur le marché du travail.
  • Open-source : Python est gratuit et peut être utilisé sans restrictions.

Histoire de Python

Python a été conçu à la fin des années 1980 par Guido van Rossum comme successeur du langage ABC. Le nom "Python" ne vient pas du serpent, mais de la série comique britannique "Monty Python's Flying Circus", dont Guido était fan.

Voici les principales étapes de l'évolution de Python :

Version Année Caractéristiques principales
Python 1.0 1994 Première version officielle
Python 2.0 2000 Introduction des listes en compréhension, garbage collection
Python 3.0 2008 Refonte majeure, non rétrocompatible avec Python 2
Python 3.6 2016 f-strings, variables annotées
Python 3.7 2018 Améliorations de performance, dictionnaires ordonnés
Python 3.8 2019 Expression d'affectation (:=), paramètres positionnels uniquement
Python 3.9 2020 Opérateurs de fusion et de mise à jour pour les dictionnaires
Python 3.10 2021 Pattern matching, améliorations des messages d'erreur
Python 3.11 2022 Performances améliorées, meilleur traçage des exceptions

Python 2 vs Python 3

Il est important de noter que Python 2 et Python 3 sont deux versions distinctes avec des différences significatives. Python 2 a atteint sa fin de vie officielle le 1er janvier 2020, ce qui signifie qu'il ne reçoit plus de mises à jour de sécurité.

Principales différences entre Python 2 et Python 3 :

  • La fonction print : En Python 2, c'est une instruction (print "Hello"), en Python 3, c'est une fonction (print("Hello")).
  • Division entière : En Python 2, 5/2 donne 2 (division entière), tandis qu'en Python 3, cela donne 2.5 (division flottante).
  • Chaînes de caractères : Python 3 gère nativement l'Unicode, contrairement à Python 2.
  • Syntaxe des exceptions : Différences dans la syntaxe pour gérer les exceptions.
  • Portée des variables : Changements dans la façon dont les variables sont traitées dans les compréhensions.

Dans ce tutoriel, nous utiliserons exclusivement Python 3, la version actuelle et recommandée.

La philosophie de Python

Python a une philosophie de conception qui privilégie la lisibilité et la simplicité. Cette philosophie est résumée dans "Le Zen de Python", accessible en tapant import this dans l'interpréteur Python :

Beau vaut mieux que laid.
Explicite vaut mieux qu'implicite.
Simple vaut mieux que complexe.
Complexe vaut mieux que compliqué.
Plat vaut mieux que imbriqué.
Clairsemé vaut mieux que dense.
La lisibilité compte.
Les cas particuliers ne sont pas assez particuliers pour enfreindre les règles.
Bien que le pragmatisme l'emporte sur la pureté.
Les erreurs ne doivent jamais passer silencieusement.
À moins d'être explicitement réduites au silence.
Face à l'ambiguïté, refusez la tentation de deviner.
Il devrait y avoir une — et de préférence une seule — façon évidente de le faire.
Bien que cette façon puisse ne pas être évidente au premier abord, à moins que vous ne soyez néerlandais.
Maintenant vaut mieux que jamais.
Bien que jamais soit souvent mieux que tout de suite.
Si l'implémentation est difficile à expliquer, c'est une mauvaise idée.
Si l'implémentation est facile à expliquer, c'est peut-être une bonne idée.
Les espaces de noms sont une excellente idée — faisons-en plus !

Installation et configuration

Installation de Python

Windows

  1. Visitez le site officiel de Python : python.org
  2. Téléchargez la dernière version de Python 3
  3. Lancez l'installateur
  4. Important : Cochez la case "Add Python to PATH" avant de commencer l'installation
  5. Cliquez sur "Install Now" pour une installation standard
  6. Une fois l'installation terminée, ouvrez l'invite de commande et tapez python --version pour vérifier l'installation

macOS

Les versions récentes de macOS peuvent déjà avoir Python installé, mais c'est souvent Python 2. Pour installer Python 3 :

  1. La méthode recommandée est d'utiliser Homebrew :

    • Installez Homebrew en ouvrant Terminal et en exécutant :
      /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
      
    • Ensuite, installez Python 3 :
      brew install python
      
  2. Alternativement, téléchargez et installez depuis python.org

  3. Vérifiez l'installation en tapant python3 --version dans Terminal

Linux

La plupart des distributions Linux viennent avec Python préinstallé. Pour installer Python 3 sur les principales distributions :

  • Ubuntu/Debian :

    sudo apt update
    sudo apt install python3 python3-pip
    
  • Fedora :

    sudo dnf install python3 python3-pip
    
  • Arch Linux :

    sudo pacman -S python python-pip
    
  • Vérifiez l'installation avec python3 --version

Environnements de développement (IDE)

Un bon environnement de développement peut considérablement améliorer votre expérience de programmation. Voici quelques options populaires :

IDLE (Integrated Development and Learning Environment)

  • Inclus avec Python
  • Interface simple, idéale pour les débutants
  • Lancement : tapez idle dans le terminal ou recherchez IDLE dans vos applications

PyCharm

  • IDE professionnel développé par JetBrains
  • Disponible en versions Community (gratuite) et Professional (payante)
  • Fonctionnalités : complétion de code, débogage, intégration git, etc.
  • Téléchargement : jetbrains.com/pycharm

Visual Studio Code

  • Éditeur de code léger mais puissant de Microsoft
  • Gratuit et open-source
  • Nécessite l'extension Python pour une expérience optimale
  • Téléchargement : code.visualstudio.com

Jupyter Notebooks

  • Idéal pour l'exploration de données et l'apprentissage
  • Permet de mélanger code, visualisations et texte explicatif
  • Installation via pip :
    pip install notebook
    
  • Lancement : jupyter notebook dans le terminal

Votre premier programme Python

Créons un programme Python simple pour vérifier que tout fonctionne correctement :

  1. Ouvrez votre éditeur de code ou IDE
  2. Créez un nouveau fichier et sauvegardez-le sous le nom hello.py
  3. Écrivez le code suivant :
print("Bonjour, monde !")
print("Bienvenue dans le monde de Python !")
  1. Exécutez le programme :
    • Dans un terminal/invite de commande : python hello.py
    • Dans IDLE : F5 ou menu Run > Run Module
    • Dans VS Code : cliquez sur le bouton play en haut à droite
    • Dans PyCharm : cliquez sur le bouton play à côté du code

Si vous voyez "Bonjour, monde !" suivi de "Bienvenue dans le monde de Python !" s'afficher, félicitations ! Vous avez exécuté votre premier programme Python.

Les bases de Python

Syntaxe et indentation

Contrairement à de nombreux langages de programmation qui utilisent des accolades {} pour définir des blocs de code, Python utilise l'indentation (espaces ou tabulations). Cette caractéristique rend le code Python naturellement lisible, mais nécessite une attention particulière à la cohérence de l'indentation.

# Exemple d'indentation en Python
if True:
    print("Cette ligne est indentée")
    if True:
        print("Cette ligne est encore plus indentée")
print("Retour à la marge")

Points importants :

  • L'indentation standard est de 4 espaces par niveau
  • Utilisez soit des espaces, soit des tabulations, mais ne les mélangez pas
  • Une indentation incorrecte provoquera une erreur IndentationError

Commentaires

Les commentaires sont des parties du code ignorées par l'interpréteur Python. Ils servent à expliquer le code et à le rendre plus compréhensible.

# Ceci est un commentaire sur une ligne

"""
Ceci est un commentaire
sur plusieurs lignes
(aussi appelé docstring quand utilisé au début d'une fonction ou classe)
"""

'''
On peut aussi utiliser des apostrophes
pour les commentaires multi-lignes
'''

x = 5  # Commentaire en fin de ligne

Affichage de texte

La fonction print() est utilisée pour afficher du texte ou des variables à l'écran :

print("Bonjour")  # Affiche: Bonjour
nom = "Alice"
print("Bonjour,", nom)  # Affiche: Bonjour, Alice

# Formatage avec f-strings (Python 3.6+)
age = 25
print(f"{nom} a {age} ans")  # Affiche: Alice a 25 ans

# Formatage avec .format()
print("{} a {} ans".format(nom, age))  # Affiche: Alice a 25 ans

# Contrôle des fins de ligne
print("Ligne 1", end=" >>> ")  # Par défaut, end="\n"
print("Même ligne")  # Affiche: Ligne 1 >>> Même ligne

Variables et types de données

Qu'est-ce qu'une variable ?

En Python, une variable est un nom qui fait référence à une valeur stockée en mémoire. Contrairement à certains langages, Python ne nécessite pas de déclaration de type explicite.

# Création et affectation de variables
x = 10
nom = "Jean"
est_actif = True

Règles de nommage des variables

  • Les noms peuvent contenir des lettres, chiffres et underscores
  • Ils doivent commencer par une lettre ou un underscore
  • Ils sont sensibles à la casse (nom et Nom sont différents)
  • Ils ne peuvent pas être un mot réservé de Python (comme if, for, while, etc.)

Conventions de nommage

  • Utilisez des noms descriptifs qui expliquent le but de la variable
  • Pour les variables ordinaires, utilisez le format snake_case (mots en minuscules séparés par des underscores)
  • Pour les constantes, utilisez des majuscules (MAX_VALUE)
  • Pour les classes, utilisez le format PascalCase (mots commençant par une majuscule sans séparation)

Types de données fondamentaux

Python possède plusieurs types de données intégrés :

1. Nombres

# Entiers (int)
a = 10
b = -5
grand_nombre = 1_000_000  # Les underscores peuvent améliorer la lisibilité

# Nombres à virgule flottante (float)
c = 3.14
d = -0.001
e = 2.5e6  # Notation scientifique (2.5 × 10^6)

# Nombres complexes
f = 2 + 3j  # j représente la partie imaginaire

2. Chaînes de caractères (str)

Les chaînes de caractères sont des séquences de caractères entourées de guillemets simples, doubles ou triples.

# Différentes façons de définir des chaînes
simple = 'Bonjour avec guillemets simples'
double = "Bonjour avec guillemets doubles"

# Chaînes multilignes
multiligne = """Ceci est une chaîne
qui s'étend sur
plusieurs lignes"""

# Caractères spéciaux et échappement
avec_apostrophe = 'L\'apostrophe doit être échappée'
ou_alternative = "L'apostrophe n'a pas besoin d'être échappée ici"
avec_guillemets = "Il a dit: \"Bonjour\""

# Caractères spéciaux courants
nouvelle_ligne = "Première ligne\nDeuxième ligne"  # \n = nouvelle ligne
tabulation = "Mot\tTabulation"  # \t = tabulation

Opérations sur les chaînes

# Concaténation
prenom = "Jean"
nom = "Dupont"
nom_complet = prenom + " " + nom  # "Jean Dupont"

# Répétition
etoiles = "*" * 5  # "*****"

# Longueur d'une chaîne
longueur = len(nom_complet)  # 11

# Accès aux caractères (indexation)
premiere_lettre = nom[0]  # "D"
derniere_lettre = nom[-1]  # "t"

# Découpage (slicing)
sous_chaine = nom_complet[0:4]  # "Jean"
debut = nom_complet[:4]  # "Jean"
fin = nom_complet[5:]  # "Dupont"
inverse = nom_complet[::-1]  # "tnopuD naeJ"

# Méthodes utiles
majuscules = nom_complet.upper()  # "JEAN DUPONT"
minuscules = nom_complet.lower()  # "jean dupont"
titre = nom_complet.title()  # "Jean Dupont"
remplacement = nom_complet.replace("Jean", "Pierre")  # "Pierre Dupont"

3. Booléens (bool)

Le type booléen ne peut prendre que deux valeurs : True ou False.

vrai = True
faux = False

# Les expressions de comparaison renvoient des booléens
a = 5
b = 10
est_egal = a == b  # False
est_superieur = a > b  # False
est_inferieur = a < b  # True

# Opérateurs logiques
et_logique = True and False  # False
ou_logique = True or False  # True
negation = not True  # False

Valeurs évaluées comme False :

  • False
  • None
  • Zéro de n'importe quel type numérique (0, 0.0)
  • Séquences et collections vides ("", [], (), {})

Tout le reste est évalué comme True.

4. Le type None

None est un type spécial qui représente l'absence de valeur ou une valeur nulle.

x = None

# Vérification de None
if x is None:
    print("x n'a pas de valeur")

Conversion de types (casting)

Python permet de convertir explicitement un type en un autre :

# Conversion en entier
x = int(3.9)  # 3 (tronque la partie décimale)
y = int("5")  # 5
z = int(True)  # 1

# Conversion en float
a = float(5)  # 5.0
b = float("2.5")  # 2.5

# Conversion en chaîne
c = str(10)  # "10"
d = str(3.14)  # "3.14"
e = str(True)  # "True"

# Conversion en booléen
f = bool(1)  # True
g = bool(0)  # False
h = bool("Bonjour")  # True (chaîne non vide)
i = bool("")  # False (chaîne vide)

Saisie utilisateur

La fonction input() permet de demander une saisie à l'utilisateur :

# Saisie basique
nom = input("Entrez votre nom : ")
print(f"Bonjour, {nom} !")

# Saisie avec conversion de type
age_str = input("Entrez votre âge : ")
age = int(age_str)  # Conversion en entier
print(f"Dans 5 ans, vous aurez {age + 5} ans.")

# Version plus concise
taille = float(input("Entrez votre taille en mètres : "))
print(f"Votre taille est de {taille} mètres.")

Opérateurs en Python

Opérateurs arithmétiques

Ces opérateurs effectuent des opérations mathématiques de base.

Opérateur Nom Exemple Résultat
+ Addition 5 + 3 8
- Soustraction 5 - 3 2
* Multiplication 5 * 3 15
/ Division 5 / 3 1.6666...
// Division entière 5 // 3 1
% Modulo (reste) 5 % 3 2
** Puissance 5 ** 3 125

Exemples :

x = 10
y = 3

print(x + y)   # 13
print(x - y)   # 7
print(x * y)   # 30
print(x / y)   # 3.3333...
print(x // y)  # 3 (partie entière de la division)
print(x % y)   # 1 (reste de la division)
print(x ** y)  # 1000 (10 à la puissance 3)

Opérateurs de comparaison

Ces opérateurs comparent deux valeurs et renvoient un booléen.

Opérateur Description Exemple Résultat
== Égal à 5 == 5 True
!= Différent de 5 != 5 False
> Supérieur à 5 > 3 True
< Inférieur à 5 < 3 False
>= Supérieur ou égal à 5 >= 5 True
<= Inférieur ou égal à 5 <= 3 False

Exemples :

a = 10
b = 20

print(a == b)  # False
print(a != b)  # True
print(a > b)   # False
print(a < b)   # True
print(a >= 10) # True
print(b <= 15) # False

Opérateurs logiques

Ces opérateurs effectuent des opérations logiques sur des booléens.

Opérateur Description Exemple Résultat
and ET logique True and False False
or OU logique True or False True
not NON logique not True False

Exemples :

x = 5
y = 10

# ET logique (toutes les conditions doivent être vraies)
print(x > 0 and y > 0)  # True
print(x > 0 and y < 0)  # False

# OU logique (au moins une condition doit être vraie)
print(x > 0 or y < 0)   # True
print(x < 0 or y < 0)   # False

# NON logique (inverse la valeur)
print(not x > 0)        # False
print(not x < 0)        # True

# Combinaisons
print((x > 0 and y > 0) or (x < 0 and y < 0))  # True

Opérateurs d'affectation

Ces opérateurs attribuent des valeurs aux variables.

Opérateur Description Exemple Équivalent à
= Affectation simple x = 5 x = 5
+= Addition et affectation x += 3 x = x + 3
-= Soustraction et affectation x -= 3 x = x - 3
*= Multiplication et affectation x *= 3 x = x * 3
/= Division et affectation x /= 3 x = x / 3
//= Division entière et affectation x //= 3 x = x // 3
%= Modulo et affectation x %= 3 x = x % 3
**= Puissance et affectation x **= 3 x = x ** 3

Exemples :

x = 10

x += 5      # x = 15
print(x)

x -= 3      # x = 12
print(x)

x *= 2      # x = 24
print(x)

x /= 6      # x = 4.0
print(x)

x = 17
x %= 5      # x = 2 (reste de 17 divisé par 5)
print(x)

x **= 3     # x = 8 (2 à la puissance 3)
print(x)

Opérateurs d'identité

Ces opérateurs vérifient si deux variables pointent vers le même objet en mémoire.

Opérateur Description Exemple
is Renvoie True si les deux variables pointent vers le même objet x is y
is not Renvoie True si les deux variables ne pointent pas vers le même objet x is not y

Exemples :

a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(a is b)      # False (même contenu mais objets différents)
print(a is c)      # True (même objet)
print(a is not b)  # True
print(a == b)      # True (même contenu)

# Cas particulier pour les petits entiers et chaînes courtes
x = 5
y = 5
print(x is y)      # True (Python optimise les petits entiers)

Note importante : N'utilisez pas is pour comparer des valeurs, utilisez ==. L'opérateur is est destiné à vérifier l'identité d'objet, pas l'égalité.

Opérateurs d'appartenance

Ces opérateurs vérifient l'appartenance d'un élément à une séquence.

Opérateur Description Exemple
in Renvoie True si l'élément est présent dans la séquence x in sequence
not in Renvoie True si l'élément n'est pas présent dans la séquence x not in sequence

Exemples :

liste = [1, 2, 3, 4, 5]
print(3 in liste)       # True
print(6 in liste)       # False
print(6 not in liste)   # True

chaine = "Bonjour"
print("on" in chaine)   # True
print("soir" in chaine) # False

dictionnaire = {"nom": "Alice", "age": 30}
print("nom" in dictionnaire)         # True (vérifie les clés)
print("Alice" in dictionnaire)       # False
print("Alice" in dictionnaire.values()) # True

Priorité des opérateurs

La priorité des opérateurs détermine l'ordre dans lequel les opérations sont effectuées. Voici l'ordre de priorité (du plus élevé au plus bas) :

Priorité Opérateur(s) Description
1 () Parenthèses
2 ** Exponentiation
3 +x, -x, ~x Positif, négatif, complément à un
4 *, /, //, % Multiplication, division, division entière, modulo
5 +, - Addition, soustraction
6 <<, >> Décalages de bits
7 & ET bit à bit
8 ^ OU exclusif bit à bit
9 ` `
10 ==, !=, >, >=, <, <=, is, is not, in, not in Comparaisons, identité, appartenance
11 not NON logique
12 and ET logique
13 or OU logique

Exemple illustrant la priorité des opérateurs :

resultat = 2 + 3 * 4     # 14 (3 * 4 est évalué en premier)
print(resultat)

resultat = (2 + 3) * 4   # 20 (les parenthèses sont évaluées en premier)
print(resultat)

resultat = 2 ** 3 * 2    # 16 (2^3 = 8, puis 8 * 2 = 16)
print(resultat)

resultat = 10 + 20 / 5   # 14.0 (20 / 5 = 4.0, puis 10 + 4.0 = 14.0)
print(resultat)

# Combinaison d'opérateurs logiques
x = 5
resultat = x > 0 and x < 10 or x == 15  # True (x > 0 and x < 10 est évalué en premier)
print(resultat)

Structures de contrôle

Les structures de contrôle permettent de diriger le flux d'exécution d'un programme. Python offre plusieurs types de structures de contrôle : les instructions conditionnelles et les boucles.

Instructions conditionnelles

Les instructions conditionnelles permettent d'exécuter différents blocs de code selon que certaines conditions sont remplies ou non.

Structure if-elif-else

age = 18

if age < 13:
    print("Enfant")
elif age < 18:
    print("Adolescent")
elif age < 65:
    print("Adulte")
else:
    print("Senior")

Conditions multiples

note = 85
presence = 75

if note >= 80 and presence >= 80:
    print("Excellent travail !")
elif note >= 70 or presence >= 90:
    print("Bon travail")
else:
    print("Des améliorations sont nécessaires")

Opérateur ternaire

L'opérateur ternaire permet d'écrire une instruction conditionnelle sur une seule ligne :

age = 20
statut = "majeur" if age >= 18 else "mineur"
print(statut)  # Affiche: majeur

Expressions conditionnelles imbriquées

age = 25
revenu = 30000

categorie = "A" if age < 30 else ("B" if revenu > 50000 else "C")
print(categorie)  # Affiche: C

Boucles

Les boucles permettent d'exécuter un bloc de code plusieurs fois.

Boucle for

La boucle for en Python est utilisée pour itérer sur une séquence (liste, tuple, dictionnaire, ensemble ou chaîne).

# Itération sur une liste
fruits = ["pomme", "banane", "cerise"]
for fruit in fruits:
    print(fruit)

# Itération avec range()
for i in range(5):  # 0, 1, 2, 3, 4
    print(i)

# range() avec début et fin
for i in range(2, 6):  # 2, 3, 4, 5
    print(i)

# range() avec pas
for i in range(0, 10, 2):  # 0, 2, 4, 6, 8
    print(i)

# Itération sur une chaîne
for lettre in "Python":
    print(lettre)

# Itération sur un dictionnaire
personne = {"nom": "Dupont", "prenom": "Jean", "age": 30}
for cle in personne:
    print(f"{cle}: {personne[cle]}")

# Méthodes alternatives pour les dictionnaires
for cle, valeur in personne.items():
    print(f"{cle}: {valeur}")

for cle in personne.keys():
    print(cle)

for valeur in personne.values():
    print(valeur)

Boucle while

La boucle while exécute un bloc de code tant qu'une condition est vraie.

# Boucle while simple
compteur = 0
while compteur < 5:
    print(compteur)
    compteur += 1

# Boucle avec condition de sortie
reponse = ""
while reponse.lower() != "q":
    reponse = input("Tapez 'q' pour quitter : ")
    print(f"Vous avez saisi : {reponse}")

# Utilisation de break pour sortir d'une boucle
while True:
    reponse = input("Tapez 'q' pour quitter : ")
    if reponse.lower() == 'q':
        break
    print(f"Vous avez saisi : {reponse}")

Instructions de contrôle de boucle

# break - Sort complètement de la boucle
for i in range(10):
    if i == 5:
        break
    print(i)  # Affiche: 0, 1, 2, 3, 4

# continue - Passe à l'itération suivante
for i in range(10):
    if i % 2 == 0:  # Si i est pair
        continue
    print(i)  # Affiche: 1, 3, 5, 7, 9

# else après une boucle - s'exécute quand la boucle se termine normalement (sans break)
for i in range(5):
    print(i)
else:
    print("Boucle terminée normalement")

# else ne s'exécute pas si la boucle est interrompue par break
for i in range(5):
    if i == 3:
        break
    print(i)
else:
    print("Ce message ne sera pas affiché")

Boucles imbriquées

# Table de multiplication
for i in range(1, 6):
    for j in range(1, 6):
        print(f"{i} × {j} = {i * j}")
    print("-" * 15)  # Séparateur

# Motif d'étoiles
for i in range(1, 6):
    print("*" * i)
# Affiche:
# *
# **
# ***
# ****
# *****

Compréhension de liste

La compréhension de liste est une façon concise de créer des listes basées sur des séquences existantes.

# Créer une liste des carrés des nombres de 0 à 9
carres = [x**2 for x in range(10)]
print(carres)  # [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

# Avec condition
pairs = [x for x in range(20) if x % 2 == 0]
print(pairs)  # [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]

# Compréhension de liste imbriquée
matrice = [[i * j for j in range(1, 4)] for i in range(1, 4)]
print(matrice)  # [[1, 2, 3], [2, 4, 6], [3, 6, 9]]

# Transformer une liste de mots
mots = ["bonjour", "python", "programmation"]
mots_majuscules = [mot.upper() for mot in mots]
print(mots_majuscules)  # ['BONJOUR', 'PYTHON', 'PROGRAMMATION']

Fonctions

Les fonctions sont des blocs de code réutilisables qui effectuent une tâche spécifique. Elles permettent de structurer votre programme, d'éviter la répétition de code et d'améliorer la lisibilité.

Définir et appeler une fonction

# Définition d'une fonction simple
def saluer():
    print("Bonjour tout le monde !")

# Appel de la fonction
saluer()  # Affiche: Bonjour tout le monde !

# Fonction avec paramètre
def saluer_personne(nom):
    print(f"Bonjour, {nom} !")

saluer_personne("Alice")  # Affiche: Bonjour, Alice !

# Fonction avec valeur de retour
def ajouter(a, b):
    return a + b

somme = ajouter(5, 3)
print(somme)  # Affiche: 8

# Fonction avec plusieurs valeurs de retour
def get_infos_personne():
    return "Jean", "Dupont", 30

prenom, nom, age = get_infos_personne()
print(f"{prenom} {nom}, {age} ans")  # Affiche: Jean Dupont, 30 ans

Paramètres de fonction

Python offre plusieurs façons de passer des paramètres à une fonction.

Paramètres obligatoires

def puissance(x, n):
    return x ** n

print(puissance(2, 3))  # Affiche: 8

Paramètres avec valeurs par défaut

def puissance(x, n=2):
    return x ** n

print(puissance(3))     # Affiche: 9 (utilise la valeur par défaut n=2)
print(puissance(3, 4))  # Affiche: 81 (utilise la valeur fournie n=4)

Arguments nommés

def saluer(prenom, nom):
    return f"Bonjour, {prenom} {nom} !"

# Appel avec arguments positionnels
print(saluer("Jean", "Dupont"))  # Affiche: Bonjour, Jean Dupont !

# Appel avec arguments nommés
print(saluer(nom="Dupont", prenom="Jean"))  # Affiche: Bonjour, Jean Dupont !

Nombre variable d'arguments

# *args permet de passer un nombre variable d'arguments positionnels
def somme(*nombres):
    resultat = 0
    for nombre in nombres:
        resultat += nombre
    return resultat

print(somme(1, 2))          # Affiche: 3
print(somme(1, 2, 3, 4, 5)) # Affiche: 15

# **kwargs permet de passer un nombre variable d'arguments nommés
def info_personne(**infos):
    for cle, valeur in infos.items():
        print(f"{cle}: {valeur}")

info_personne(nom="Dupont", prenom="Jean", age=30, ville="Paris")

Combinaison des différents types de paramètres

def fonction_complete(param_obligatoire, param_defaut=10, *args, **kwargs):
    print(f"Paramètre obligatoire: {param_obligatoire}")
    print(f"Paramètre avec valeur par défaut: {param_defaut}")
    print(f"Arguments variables (*args): {args}")
    print(f"Arguments nommés variables (**kwargs): {kwargs}")

fonction_complete(1, 20, 3, 4, 5, nom="Dupont", ville="Paris")
# Affiche:
# Paramètre obligatoire: 1
# Paramètre avec valeur par défaut: 20
# Arguments variables (*args): (3, 4, 5)
# Arguments nommés variables (**kwargs): {'nom': 'Dupont', 'ville': 'Paris'}

Portée des variables

La portée d'une variable détermine où cette variable peut être utilisée dans le code.

# Variable globale
x = 10

def fonction1():
    # Variable locale
    y = 5
    print(f"Dans fonction1: x = {x}, y = {y}")

def fonction2():
    # Redéfinition locale de x
    x = 20
    print(f"Dans fonction2: x = {x}")

def fonction3():
    # Pour modifier une variable globale
    global x
    x = 30
    print(f"Dans fonction3: x = {x}")

fonction1()  # Affiche: Dans fonction1: x = 10, y = 5
fonction2()  # Affiche: Dans fonction2: x = 20
print(f"Après fonction2: x = {x}")  # Affiche: Après fonction2: x = 10
fonction3()  # Affiche: Dans fonction3: x = 30
print(f"Après fonction3: x = {x}")  # Affiche: Après fonction3: x = 30

Fonctions lambda

Les fonctions lambda sont des fonctions anonymes définies sur une seule ligne.

# Fonction lambda simple
carre = lambda x: x ** 2
print(carre(5))  # Affiche: 25

# Fonction lambda avec plusieurs paramètres
addition = lambda x, y: x + y
print(addition(3, 4))  # Affiche: 7

# Utilisation avec map()
nombres = [1, 2, 3, 4, 5]
carres = list(map(lambda x: x ** 2, nombres))
print(carres)  # Affiche: [1, 4, 9, 16, 25]

# Utilisation avec filter()
nombres = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
pairs = list(filter(lambda x: x % 2 == 0, nombres))
print(pairs)  # Affiche: [2, 4, 6, 8, 10]

# Utilisation avec sorted()
etudiants = [
    {"nom": "Alice", "notes": 85},
    {"nom": "Bob", "notes": 75},
    {"nom": "Charlie", "notes": 90}
]
etudiants_tries = sorted(etudiants, key=lambda e: e["notes"], reverse=True)
print(etudiants_tries)

Récursivité

Une fonction récursive est une fonction qui s'appelle elle-même.

# Calcul du factoriel avec récursivité
def factoriel(n):
    if n <= 1:
        return 1
    else:
        return n * factoriel(n - 1)

print(factoriel(5))  # Affiche: 120 (5! = 5 * 4 * 3 * 2 * 1)

# Calcul de la suite de Fibonacci avec récursivité
def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

for i in range(10):
    print(fibonacci(i), end=" ")  # Affiche: 0 1 1 2 3 5 8 13 21 34

Décorateurs

Les décorateurs sont un moyen d'étendre ou de modifier le comportement des fonctions.

# Définition d'un décorateur simple
def mon_decorateur(fonction):
    def wrapper():
        print("Avant l'appel de la fonction")
        fonction()
        print("Après l'appel de la fonction")
    return wrapper

# Utilisation du décorateur
@mon_decorateur
def dire_bonjour():
    print("Bonjour !")

dire_bonjour()
# Affiche:
# Avant l'appel de la fonction
# Bonjour !
# Après l'appel de la fonction

# Décorateur avec arguments
def repeter(n):
    def decorateur(fonction):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                resultat = fonction(*args, **kwargs)
            return resultat
        return wrapper
    return decorateur

@repeter(3)
def dire_message(message):
    print(message)

dire_message("Hello")
# Affiche:
# Hello
# Hello
# Hello

Structures de données

Les structures de données permettent de stocker et d'organiser les données dans votre programme. Python offre plusieurs structures de données intégrées.

Listes

Les listes sont des collections ordonnées et modifiables d'éléments.

# Création de listes
liste_vide = []
nombres = [1, 2, 3, 4, 5]
mixte = [1, "texte", 3.14, True]
imbriquee = [1, [2, 3], 4]

# Accès aux éléments
premier = nombres[0]  # 1
dernier = nombres[-1]  # 5
sous_liste = nombres[1:4]  # [2, 3, 4]

# Modification des éléments
nombres[0] = 10
print(nombres)  # [10, 2, 3, 4, 5]

# Méthodes courantes
nombres.append(6)  # Ajoute à la fin: [10, 2, 3, 4, 5, 6]
nombres.insert(1, 15)  # Insère à l'index 1: [10, 15, 2, 3, 4, 5, 6]
nombres.remove(3)  # Supprime la première occurrence de 3: [10, 15, 2, 4, 5, 6]
valeur = nombres.pop()  # Supprime et renvoie le dernier élément: 6
valeur = nombres.pop(1)  # Supprime et renvoie l'élément à l'index 1: 15
indice = nombres.index(4)  # Renvoie l'index de la première occurrence de 4: 2
count = nombres.count(10)  # Compte les occurrences de 10: 1
nombres.sort()  # Trie la liste en place: [2, 4, 5, 10]
nombres.reverse()  # Inverse la liste en place: [10, 5, 4, 2]
copie = nombres.copy()  # Crée une copie superficielle

# Opérations sur les listes
liste1 = [1, 2, 3]
liste2 = [4, 5, 6]
concatenee = liste1 + liste2  # [1, 2, 3, 4, 5, 6]
repetee = liste1 * 3  # [1, 2, 3, 1, 2, 3, 1, 2, 3]
taille = len(liste1)  # 3

Tuples

Les tuples sont des collections ordonnées et immuables d'éléments.

# Création de tuples
tuple_vide = ()
singleton = (1,)  # La virgule est nécessaire pour un tuple d'un seul élément
coordonnees = (10, 20)
personne = ("Jean", "Dupont", 30)

# Déballage de tuple
prenom, nom, age = personne
print(f"{prenom} {nom}, {age} ans")

# Accès aux éléments (comme pour les listes)
x = coordonnees[0]  # 10
y = coordonnees[1]  # 20

# Méthodes de tuple
count = personne.count("Jean")  # 1
index = personne.index(30)  # 2

# Conversion entre listes et tuples
liste = list(coordonnees)  # [10, 20]
tuple_depuis_liste = tuple([1, 2, 3])  # (1, 2, 3)

# Avantages des tuples par rapport aux listes
# - Plus rapides que les listes
# - Peuvent être utilisés comme clés de dictionnaire
# - Garantie que les données ne seront pas modifiées

Dictionnaires

Les dictionnaires sont des collections non ordonnées de paires clé-valeur.

# Création de dictionnaires
dict_vide = {}
personne = {"nom": "Dupont", "prenom": "Jean", "age": 30}
coordonnees = dict(x=10, y=20)

# Accès aux valeurs
nom = personne["nom"]  # "Dupont"
# Si la clé peut ne pas exister, utilisez get
prenom = personne.get("prenom", "Inconnu")  # "Jean"
ville = personne.get("ville", "Inconnue")  # "Inconnue" (clé absente)

# Modification et ajout
personne["age"] = 31  # Modifie la valeur existante
personne["ville"] = "Paris"  # Ajoute une nouvelle paire clé-valeur

# Méthodes de dictionnaire
cles = personne.keys()  # dict_keys(['nom', 'prenom', 'age', 'ville'])
valeurs = personne.values()  # dict_values(['Dupont', 'Jean', 31, 'Paris'])
items = personne.items()  # dict_items([('nom', 'Dupont'), ('prenom', 'Jean'), ('age', 31), ('ville', 'Paris')])

# Supprimer une entrée
ville = personne.pop("ville")  # Supprime et renvoie la valeur: "Paris"
dernier = personne.popitem()  # Supprime et renvoie le dernier item: ('age', 31)

# Fusion de dictionnaires (Python 3.5+)
dict1 = {"a": 1, "b": 2}
dict2 = {"b": 3, "c": 4}
fusion = {**dict1, **dict2}  # {'a': 1, 'b': 3, 'c': 4}

# Fusion de dictionnaires (Python 3.9+)
fusion = dict1 | dict2  # {'a': 1, 'b': 3, 'c': 4}

# Compréhension de dictionnaire
carre_dict = {x: x**2 for x in range(5)}  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

Ensembles (Sets)

Les ensembles sont des collections non ordonnées d'éléments uniques.

# Création d'ensembles
ensemble_vide = set()
couleurs = {"rouge", "vert", "bleu"}
nombres = set([1, 2, 3, 2, 1])  # {1, 2, 3} (doublons supprimés)

# Ajout et suppression d'éléments
couleurs.add("jaune")  # {"rouge", "vert", "bleu", "jaune"}
couleurs.remove("vert")  # Lève une erreur si l'élément n'existe pas
couleurs.discard("orange")  # Ne lève pas d'erreur si l'élément n'existe pas
element = couleurs.pop()  # Supprime et renvoie un élément arbitraire

# Opérations sur les ensembles
set1 = {1, 2, 3, 4, 5}
set2 = {4, 5, 6, 7, 8}

union = set1 | set2  # {1, 2, 3, 4, 5, 6, 7, 8}
intersection = set1 & set2  # {4, 5}
difference = set1 - set2  # {1, 2, 3}
diff_symetrique = set1 ^ set2  # {1, 2, 3, 6, 7, 8}

# Tests sur les ensembles
print(1 in set1)  # True
print(set1.issubset(set2))  # False
print(set1.issuperset({1, 2}))  # True
print(set1.isdisjoint(set2))  # False (ils ont des éléments en commun)

# Compréhension d'ensemble
pairs = {x for x in range(10) if x % 2 == 0}  # {0, 2, 4, 6, 8}

Comparaison des structures de données

Voici un tableau comparatif des principales structures de données en Python :

Caractéristique Liste Tuple Dictionnaire Ensemble
Mutabilité Mutable Immuable Mutable Mutable
Ordonné Oui Oui Non* Non
Indexable Oui Oui Par clé Non
Doublons Autorisés Autorisés Clés uniques Éléments uniques
Délimitation [] () {} {}
Création vide [] () {} set()
Exemple d'utilisation Séquence ordonnée d'items Données immuables, retour multiple de fonction Associations clé-valeur Élimination des doublons, opérations d'ensemble

* À partir de Python 3.7, les dictionnaires conservent l'ordre d'insertion, mais cela ne fait pas partie de leur définition théorique.

Modules et packages

Python utilise des modules et des packages pour organiser et réutiliser le code. Un module est simplement un fichier Python contenant du code. Un package est un dossier contenant plusieurs modules.

Importer des modules

# Import basique
import math
print(math.sqrt(16))  # 4.0

# Import avec alias
import math as m
print(m.sqrt(16))  # 4.0

# Import sélectif
from math import sqrt, pi
print(sqrt(16))  # 4.0
print(pi)  # 3.141592653589793

# Import de tout le contenu (à éviter généralement)
from math import *
print(cos(0))  # 1.0

Créer vos propres modules

Supposons que vous avez un fichier calculs.py :

# calculs.py
def ajouter(a, b):
    return a + b

def multiplier(a, b):
    return a * b

PI = 3.14159

Vous pouvez l'importer dans un autre fichier :

# main.py
import calculs

print(calculs.ajouter(5, 3))  # 8
print(calculs.PI)  # 3.14159

from calculs import multiplier
print(multiplier(4, 5))  # 20

Structure d'un package

Un package est un répertoire qui contient un fichier spécial __init__.py et des modules Python.

mon_package/
    __init__.py
    module1.py
    module2.py
    sous_package/
        __init__.py
        module3.py

Le fichier __init__.py peut être vide ou contenir du code d'initialisation.

Utilisation de pip

pip est le gestionnaire de packages Python qui permet d'installer des packages tiers.

# Installer un package
pip install numpy

# Installer une version spécifique
pip install numpy==1.19.0

# Mettre à jour un package
pip install --upgrade numpy

# Désinstaller un package
pip uninstall numpy

# Lister les packages installés
pip list

# Enregistrer les dépendances
pip freeze > requirements.txt

# Installer à partir d'un fichier requirements.txt
pip install -r requirements.txt

Environnements virtuels

Les environnements virtuels permettent de créer des environnements Python isolés pour chaque projet.

# Créer un environnement virtuel
python -m venv mon_env

# Activer l'environnement
# Sur Windows
mon_env\Scripts\activate
# Sur Unix ou MacOS
source mon_env/bin/activate

# Désactiver l'environnement
deactivate

Modules standard essentiels

Python dispose d'une riche bibliothèque standard. Voici quelques modules utiles :

# os - Interface avec le système d'exploitation
import os
print(os.getcwd())  # Répertoire de travail actuel
os.mkdir("nouveau_dossier")  # Crée un dossier
print(os.listdir())  # Liste les fichiers et dossiers

# sys - Variables et fonctions spécifiques au système
import sys
print(sys.version)  # Version de Python
print(sys.argv)  # Arguments de ligne de commande
sys.exit(0)  # Termine le programme

# datetime - Manipulation de dates et heures
from datetime import datetime, timedelta
maintenant = datetime.now()
print(maintenant)
dans_une_semaine = maintenant + timedelta(days=7)
print(dans_une_semaine)

# random - Génération de nombres aléatoires
import random
print(random.randint(1, 10))  # Entier aléatoire entre 1 et 10
print(random.choice(["rouge", "vert", "bleu"]))  # Élément aléatoire
random.shuffle(ma_liste)  # Mélange une liste en place

# json - Encodage et décodage JSON
import json
donnees = {"nom": "Jean", "age": 30, "ville": "Paris"}
json_str = json.dumps(donnees)  # Conversion en chaîne JSON
print(json_str)
obj = json.loads(json_str)  # Conversion d'une chaîne JSON en objet Python
print(obj["nom"])

Gestion des fichiers

La manipulation de fichiers est une tâche courante en programmation. Python offre plusieurs méthodes pour lire et écrire des fichiers.

Opérations de base sur les fichiers

# Ouvrir un fichier en mode lecture
with open("exemple.txt", "r") as f:
    contenu = f.read()  # Lit tout le fichier
    print(contenu)

# Ouvrir un fichier en mode écriture (écrase le contenu existant)
with open("exemple.txt", "w") as f:
    f.write("Bonjour, monde !\n")
    f.write("Ceci est un exemple de fichier texte.")

# Ouvrir un fichier en mode ajout (ajoute à la fin du fichier)
with open("exemple.txt", "a") as f:
    f.write("\nCette ligne est ajoutée.")

# Lire ligne par ligne
with open("exemple.txt", "r") as f:
    for ligne in f:
        print(ligne.strip())  # strip() supprime les espaces et \n

# Lire toutes les lignes dans une liste
with open("exemple.txt", "r") as f:
    lignes = f.readlines()
    print(lignes)

Modes d'ouverture de fichiers

Mode Description
'r' Lecture seule (défaut)
'w' Écriture (écrase le fichier existant)
'a' Ajout (ajoute à la fin du fichier)
'x' Création exclusive (échoue si le fichier existe)
'b' Mode binaire (peut être combiné avec d'autres modes)
't' Mode texte (défaut, peut être combiné avec d'autres modes)
'+' Lecture et écriture (peut être combiné avec d'autres modes)

Travailler avec des fichiers CSV

Le format CSV (Comma-Separated Values) est couramment utilisé pour stocker des données tabulaires.

import csv

# Écrire dans un fichier CSV
with open("donnees.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["Nom", "Âge", "Ville"])  # Écrire l'en-tête
    writer.writerow(["Jean", 30, "Paris"])
    writer.writerow(["Marie", 25, "Lyon"])
    writer.writerow(["Pierre", 35, "Marseille"])

# Lire un fichier CSV
with open("donnees.csv", "r", newline="") as f:
    reader = csv.reader(f)
    for row in reader:
        print(row)

# Utiliser DictReader et DictWriter
with open("donnees.csv", "r", newline="") as f:
    reader = csv.DictReader(f)
    for row in reader:
        print(f"{row['Nom']} a {row['Âge']} ans et vit à {row['Ville']}")

with open("employes.csv", "w", newline="") as f:
    fieldnames = ["id", "nom", "salaire"]
    writer = csv.DictWriter(f, fieldnames=fieldnames)
    writer.writeheader()
    writer.writerow({"id": 1, "nom": "Alice", "salaire": 50000})
    writer.writerow({"id": 2, "nom": "Bob", "salaire": 60000})

Travailler avec des fichiers JSON

JSON (JavaScript Object Notation) est un format léger d'échange de données.

import json

# Écrire dans un fichier JSON
donnees = {
    "personnes": [
        {"nom": "Jean", "age": 30, "ville": "Paris"},
        {"nom": "Marie", "age": 25, "ville": "Lyon"},
        {"nom": "Pierre", "age": 35, "ville": "Marseille"}
    ]
}

with open("donnees.json", "w") as f:
    json.dump(donnees, f, indent=4)  # indent pour une mise en forme lisible

# Lire un fichier JSON
with open("donnees.json", "r") as f:
    donnees_chargees = json.load(f)
    
for personne in donnees_chargees["personnes"]:
    print(f"{personne['nom']} a {personne['age']} ans")

Gestion des chemins avec pathlib

Le module pathlib offre une interface orientée objet pour manipuler les chemins de fichiers.

from pathlib import Path

# Création d'objets Path
chemin_actuel = Path.cwd()  # Répertoire de travail actuel
chemin_fichier = Path("dossier") / "sous_dossier" / "fichier.txt"

# Informations sur le chemin
print(chemin_fichier.name)  # fichier.txt
print(chemin_fichier.stem)  # fichier
print(chemin_fichier.suffix)  # .txt
print(chemin_fichier.parent)  # dossier/sous_dossier

# Opérations sur les chemins
if not chemin_fichier.exists():
    chemin_fichier.parent.mkdir(parents=True, exist_ok=True)
    chemin_fichier.touch()

# Lister les fichiers d'un répertoire
for fichier in Path("dossier").glob("*.txt"):
    print(fichier)

# Lire et écrire des fichiers avec pathlib
texte = chemin_fichier.read_text(encoding="utf-8")
chemin_fichier.write_text("Nouveau contenu", encoding="utf-8")

Gestion des exceptions

Les exceptions sont des erreurs détectées pendant l'exécution du programme. Python fournit un mécanisme puissant pour gérer ces erreurs.

Structure try-except

# Structure try-except de base
try:
    x = 10 / 0  # Génère une ZeroDivisionError
except ZeroDivisionError:
    print("Erreur : Division par zéro !")

# Gérer plusieurs exceptions
try:
    nombre = int(input("Entrez un nombre : "))
    resultat = 10 / nombre
    print(f"Résultat : {resultat}")
except ValueError:
    print("Erreur : Veuillez entrer un nombre valide !")
except ZeroDivisionError:
    print("Erreur : Division par zéro !")

# Capturer l'objet exception
try:
    fichier = open("fichier_inexistant.txt", "r")
except FileNotFoundError as e:
    print(f"Erreur : {e}")

# Clause else (exécutée si aucune exception n'est levée)
try:
    nombre = int(input("Entrez un nombre : "))
    resultat = 10 / nombre
except (ValueError, ZeroDivisionError):
    print("Une erreur s'est produite !")
else:
    print(f"Résultat : {resultat}")

# Clause finally (toujours exécutée)
try:
    fichier = open("exemple.txt", "r")
    contenu = fichier.read()
except FileNotFoundError:
    print("Le fichier n'existe pas !")
finally:
    # Ce bloc s'exécute qu'il y ait une exception ou non
    print("Opération terminée.")
    # Fermer le fichier si ouvert
    if 'fichier' in locals() and not fichier.closed:
        fichier.close()

Lever des exceptions

# Lever une exception explicitement
def diviser(a, b):
    if b == 0:
        raise ValueError("Division par zéro impossible !")
    return a / b

try:
    resultat = diviser(10, 0)
except ValueError as e:
    print(f"Erreur : {e}")

# Re-lever une exception
try:
    x = int("abc")
except ValueError:
    print("Conversion échouée")
    raise  # Re-lève l'exception d'origine

Créer des exceptions personnalisées

# Définir une exception personnalisée
class AgeInvalideError(Exception):
    """Exception levée quand l'âge est invalide."""
    pass

def verifier_age(age):
    if age < 0:
        raise AgeInvalideError("L'âge ne peut pas être négatif")
    if age > 120:
        raise AgeInvalideError("L'âge semble trop élevé")
    return True

try:
    verifier_age(-5)
except AgeInvalideError as e:
    print(f"Erreur de validation : {e}")

Assertions

Les assertions sont utilisées pour vérifier qu'une condition est vraie à un certain point du programme.

def calculer_racine_carree(nombre):
    assert nombre >= 0, "Le nombre doit être positif ou nul"
    return nombre ** 0.5

# Fonctionne
print(calculer_racine_carree(16))  # 4.0

# Lève une AssertionError
try:
    print(calculer_racine_carree(-16))
except AssertionError as e:
    print(f"Erreur : {e}")

Programmation orientée objet

La programmation orientée objet (POO) est un paradigme de programmation qui utilise des "objets" et leurs interactions pour concevoir des applications. Python est un langage orienté objet.

Classes et objets

# Définition d'une classe simple
class Personne:
    """Classe représentant une personne."""
    
    def __init__(self, nom, age):
        """Initialise une nouvelle personne."""
        self.nom = nom
        self.age = age
    
    def se_presenter(self):
        """Affiche une présentation de la personne."""
        print(f"Bonjour, je m'appelle {self.nom} et j'ai {self.age} ans.")

# Création d'objets (instances de la classe)
p1 = Personne("Alice", 30)
p2 = Personne("Bob", 25)

# Appel de méthodes
p1.se_presenter()  # Bonjour, je m'appelle Alice et j'ai 30 ans.
p2.se_presenter()  # Bonjour, je m'appelle Bob et j'ai 25 ans.

# Accès aux attributs
print(p1.nom)  # Alice
p1.age = 31  # Modification d'un attribut
p1.se_presenter()  # Bonjour, je m'appelle Alice et j'ai 31 ans.

Héritage

L'héritage permet à une classe d'acquérir les attributs et méthodes d'une autre classe.

# Classe de base
class Animal:
    def __init__(self, nom):
        self.nom = nom
    
    def faire_bruit(self):
        pass  # Méthode à surcharger dans les classes dérivées

# Classes dérivées
class Chien(Animal):
    def faire_bruit(self):
        return f"{self.nom} dit Woof!"

class Chat(Animal):
    def faire_bruit(self):
        return f"{self.nom} dit Meow!"

# Utilisation des classes dérivées
mon_chien = Chien("Rex")
mon_chat = Chat("Minou")

print(mon_chien.faire_bruit())  # Rex dit Woof!
print(mon_chat.faire_bruit())   # Minou dit Meow!

# Vérification du type
print(isinstance(mon_chien, Chien))  # True
print(isinstance(mon_chien, Animal))  # True
print(isinstance(mon_chat, Chien))   # False

Héritage multiple

Python permet l'héritage multiple, où une classe peut hériter de plusieurs classes.

class A:
    def methode(self):
        return "Méthode de A"

class B:
    def methode(self):
        return "Méthode de B"
    
    def autre_methode(self):
        return "Autre méthode de B"

# C hérite de A et B (l'ordre est important)
class C(A, B):
    pass

obj = C()
print(obj.methode())  # "Méthode de A" (première classe dans l'ordre d'héritage)
print(obj.autre_methode())  # "Autre méthode de B"

Encapsulation

L'encapsulation consiste à restreindre l'accès à certains composants d'un objet.

class CompteBancaire:
    def __init__(self, solde_initial=0):
        # Attribut "privé" (convention de nommage)
        self._solde = solde_initial
    
    # Getter
    @property
    def solde(self):
        return self._solde
    
    # Setter
    @solde.setter
    def solde(self, valeur):
        if valeur < 0:
            raise ValueError("Le solde ne peut pas être négatif")
        self._solde = valeur
    
    def deposer(self, montant):
        if montant <= 0:
            raise ValueError("Le montant doit être positif")
        self._solde += montant
    
    def retirer(self, montant):
        if montant <= 0:
            raise ValueError("Le montant doit être positif")
        if montant > self._solde:
            raise ValueError("Fonds insuffisants")
        self._solde -= montant

# Utilisation
compte = CompteBancaire(1000)
print(compte.solde)  # 1000

compte.deposer(500)
print(compte.solde)  # 1500

try:
    compte.retirer(2000)  # Lève une exception
except ValueError as e:
    print(f"Erreur : {e}")

# Utilisation du setter
compte.solde = 2000
print(compte.solde)  # 2000

try:
    compte.solde = -100  # Lève une exception
except ValueError as e:
    print(f"Erreur : {e}")

Polymorphisme

Le polymorphisme permet de traiter des objets de différentes classes de manière uniforme.

class Animal:
    def parler(self):
        pass

class Chien(Animal):
    def parler(self):
        return "Woof!"

class Chat(Animal):
    def parler(self):
        return "Meow!"

class Canard(Animal):
    def parler(self):
        return "Coin!"

# Fonction polymorphique
def faire_parler_animal(animal):
    return animal.parler()

# Utilisation
animaux = [Chien(), Chat(), Canard()]
for animal in animaux:
    print(faire_parler_animal(animal))

Méthodes spéciales

Python utilise des méthodes spéciales (ou "magic methods") pour définir comment les objets se comportent dans certaines situations.

class Vecteur:
    def __init__(self, x, y):
        self.x = x
        self.y = y
    
    # Représentation pour print()
    def __str__(self):
        return f"Vecteur({self.x}, {self.y})"
    
    # Représentation pour le débogage
    def __repr__(self):
        return f"Vecteur({self.x}, {self.y})"
    
    # Addition de vecteurs
    def __add__(self, autre):
        return Vecteur(self.x + autre.x, self.y + autre.y)
    
    # Soustraction de vecteurs
    def __sub__(self, autre):
        return Vecteur(self.x - autre.x, self.y - autre.y)
    
    # Multiplication par un scalaire
    def __mul__(self, scalaire):
        return Vecteur(self.x * scalaire, self.y * scalaire)
    
    # Égalité
    def __eq__(self, autre):
        return self.x == autre.x and self.y == autre.y
    
    # Longueur (norme) du vecteur
    def __abs__(self):
        return (self.x ** 2 + self.y ** 2) ** 0.5
    
    # Permet d'utiliser len()
    def __len__(self):
        return int(abs(self))

# Utilisation
v1 = Vecteur(3, 4)
v2 = Vecteur(1, 2)

print(v1)            # Vecteur(3, 4)
print(v1 + v2)       # Vecteur(4, 6)
print(v1 - v2)       # Vecteur(2, 2)
print(v1 * 2)        # Vecteur(6, 8)
print(v1 == v2)      # False
print(abs(v1))       # 5.0 (norme du vecteur)
print(len(v1))       # 5

Bibliothèques standard

Python est accompagné d'une riche bibliothèque standard. Voici quelques modules importants et leur utilisation.

Module datetime

from datetime import datetime, date, time, timedelta

# Date et heure actuelles
maintenant = datetime.now()
print(maintenant)  # 2023-09-15 14:30:45.123456

# Créer une date spécifique
naissance = date(1990, 5, 15)
print(naissance)  # 1990-05-15

# Créer une heure spécifique
heure_reunion = time(14, 30)
print(heure_reunion)  # 14:30:00

# Créer un datetime spécifique
rendez_vous = datetime(2023, 10, 1, 10, 0)
print(rendez_vous)  # 2023-10-01 10:00:00

# Calcul avec les dates
age = date.today().year - naissance.year
print(f"Âge approximatif : {age} ans")

# Ajouter ou soustraire du temps
demain = date.today() + timedelta(days=1)
dans_une_heure = datetime.now() + timedelta(hours=1)
il_y_a_une_semaine = date.today() - timedelta(weeks=1)

# Formatage des dates
print(maintenant.strftime("%d/%m/%Y %H:%M"))  # 15/09/2023 14:30
print(maintenant.strftime("%A %d %B %Y"))     # Friday 15 September 2023

# Parsing des dates
date_str = "15/09/2023 14:30"
date_obj = datetime.strptime(date_str, "%d/%m/%Y %H:%M")
print(date_obj)  # 2023-09-15 14:30:00

Module random

import random

# Nombres aléatoires
print(random.random())        # Nombre à virgule entre 0 et 1
print(random.uniform(1, 10))  # Nombre à virgule entre 1 et 10
print(random.randint(1, 100)) # Entier entre 1 et 100 inclus
print(random.randrange(0, 101, 2))  # Entier pair entre 0 et 100

# Sélection aléatoire
fruits = ["pomme", "banane", "orange", "raisin"]
print(random.choice(fruits))   # Un élément aléatoire
print(random.sample(fruits, 2))  # Deux éléments aléatoires sans répétition
print(random.choices(fruits, k=3))  # Trois éléments aléatoires avec possible répétition

# Mélanger une liste
cartes = ["A", "K", "Q", "J", "10", "9", "8", "7"]
random.shuffle(cartes)
print(cartes)  # Liste mélangée de façon aléatoire

# Pour la reproductibilité
random.seed(42)  # Fixe la graine aléatoire

Module collections

from collections import Counter, defaultdict, namedtuple, deque

# Counter - compte les occurrences d'éléments
mots = ["chat", "chien", "chat", "poisson", "chien", "chat"]
compteur = Counter(mots)
print(compteur)  # Counter({'chat': 3, 'chien': 2, 'poisson': 1})
print(compteur["chat"])  # 3
print(compteur.most_common(2))  # [('chat', 3), ('chien', 2)]

# defaultdict - dictionnaire avec valeur par défaut
fruits_par_couleur = defaultdict(list)
fruits_par_couleur["rouge"].append("pomme")
fruits_par_couleur["rouge"].append("fraise")
fruits_par_couleur["jaune"].append("banane")
print(fruits_par_couleur)  # defaultdict(<class 'list'>, {'rouge': ['pomme', 'fraise'], 'jaune': ['banane']})
print(fruits_par_couleur["verte"])  # [] (crée une liste vide pour une clé inexistante)

# namedtuple - tuple nommé
Point = namedtuple('Point', ['x', 'y'])
p = Point(10, 20)
print(p.x, p.y)  # 10 20
print(p[0], p[1])  # 10 20

# deque - file double
file = deque(["a", "b", "c"])
file.append("d")        # Ajoute à droite
file.appendleft("z")    # Ajoute à gauche
print(file)             # deque(['z', 'a', 'b', 'c', 'd'])
print(file.pop())       # 'd' (retire de la droite)
print(file.popleft())   # 'z' (retire de la gauche)
file.rotate(1)          # Rotation vers la droite
print(file)             # deque(['c', 'a', 'b'])

Module itertools

import itertools

# count - génère des nombres à l'infini
for i in itertools.islice(itertools.count(10, 2), 5):  # Commence à 10, pas de 2, prend 5 éléments
    print(i, end=" ")  # 10 12 14 16 18
print()

# cycle - cycle à travers une séquence indéfiniment
couleurs = itertools.cycle(["rouge", "vert", "bleu"])
for i, couleur in enumerate(itertools.islice(couleurs, 7)):
    print(f"Élément {i}: {couleur}")

# repeat - répète un élément
for x in itertools.repeat("Python", 3):
    print(x)  # Python Python Python

# product - produit cartésien
for combo in itertools.product("AB", "12"):
    print("".join(combo), end=" ")  # A1 A2 B1 B2
print()

# permutations - toutes les permutations possibles
for p in itertools.permutations("ABC", 2):
    print("".join(p), end=" ")  # AB AC BA BC CA CB
print()

# combinations - toutes les combinaisons possibles sans répétition
for c in itertools.combinations("ABCD", 2):
    print("".join(c), end=" ")  # AB AC AD BC BD CD
print()

Module re (expressions régulières)

import re

# Recherche simple
texte = "Mon adresse email est exemple@email.com"
match = re.search(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b", texte)
if match:
    print("Email trouvé:", match.group())  # exemple@email.com

# Trouver toutes les correspondances
texte = "Contactez-nous à support@entreprise.fr ou info@entreprise.fr"
emails = re.findall(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b", texte)
print(emails)  # ['support@entreprise.fr', 'info@entreprise.fr']

# Remplacement
texte = "Mon numéro est 123-456-7890."
texte_modifie = re.sub(r"(\d{3})-(\d{3})-(\d{4})", r"(\1) \2-\3", texte)
print(texte_modifie)  # Mon numéro est (123) 456-7890.

# Séparation
texte = "pomme,banane,orange;raisin:fraise"
fruits = re.split(r"[,;:]", texte)
print(fruits)  # ['pomme', 'banane', 'orange', 'raisin', 'fraise']

# Validation avec match
def est_email_valide(email):
    pattern = r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}$"
    return bool(re.match(pattern, email))

print(est_email_valide("valide@email.com"))  # True
print(est_email_valide("invalide@email"))    # False

Projets pratiques

Dans cette section, nous allons développer quelques projets pratiques pour mettre en application les connaissances acquises.

Projet 1 : Calculatrice simple

def calculatrice():
    """Calculatrice en ligne de commande."""
    print("Calculatrice Python")
    print("Opérations disponibles: +, -, *, /, ** (puissance)")
    print("Tapez 'q' pour quitter")
    
    while True:
        # Récupérer l'entrée utilisateur
        expression = input("\nEntrez une expression (ex: 2 + 3): ")
        
        # Quitter si demandé
        if expression.lower() == 'q':
            print("Au revoir !")
            break
        
        # Essayer d'évaluer l'expression
        try:
            # Utiliser eval() avec précaution !
            result = eval(expression)
            print(f"Résultat: {result}")
        except Exception as e:
            print(f"Erreur: {e}")

# Lancer la calculatrice
calculatrice()

Projet 2 : Gestionnaire de tâches

class GestionnaireTaches:
    def __init__(self):
        self.taches = []
    
    def ajouter_tache(self, tache):
        """Ajoute une nouvelle tâche."""
        self.taches.append({"tache": tache, "terminee": False})
        print(f"Tâche '{tache}' ajoutée.")
    
    def afficher_taches(self):
        """Affiche toutes les tâches."""
        if not self.taches:
            print("Aucune tâche à afficher.")
            return
        
        print("\nListe des tâches:")
        for i, tache in enumerate(self.taches, 1):
            statut = "✓" if tache["terminee"] else " "
            print(f"{i}. [{statut}] {tache['tache']}")
    
    def marquer_terminee(self, index):
        """Marque une tâche comme terminée."""
        try:
            # Ajuster l'index (l'utilisateur commence à 1, la liste à 0)
            index = int(index) - 1
            if 0 <= index < len(self.taches):
                self.taches[index]["terminee"] = True
                print(f"Tâche '{self.taches[index]['tache']}' marquée comme terminée.")
            else:
                print("Index de tâche invalide.")
        except ValueError:
            print("Veuillez entrer un numéro valide.")
    
    def supprimer_tache(self, index):
        """Supprime une tâche."""
        try:
            # Ajuster l'index
            index = int(index) - 1
            if 0 <= index < len(self.taches):
                tache_supprimee = self.taches.pop(index)
                print(f"Tâche '{tache_supprimee['tache']}' supprimée.")
            else:
                print("Index de tâche invalide.")
        except ValueError:
            print("Veuillez entrer un numéro valide.")
    
    def menu(self):
        """Affiche le menu principal."""
        print("\nGestionnaire de Tâches")
        print("1. Ajouter une tâche")
        print("2. Afficher les tâches")
        print("3. Marquer une tâche comme terminée")
        print("4. Supprimer une tâche")
        print("5. Quitter")
        return input("Choisissez une option (1-5): ")

# Programme principal
def main():
    gestionnaire = GestionnaireTaches()
    
    while True:
        choix = gestionnaire.menu()
        
        if choix == "1":
            tache = input("Entrez la description de la tâche: ")
            gestionnaire.ajouter_tache(tache)
        elif choix == "2":
            gestionnaire.afficher_taches()
        elif choix == "3":
            gestionnaire.afficher_taches()
            index = input("Entrez le numéro de la tâche à marquer comme terminée: ")
            gestionnaire.marquer_terminee(index)
        elif choix == "4":
            gestionnaire.afficher_taches()
            index = input("Entrez le numéro de la tâche à supprimer: ")
            gestionnaire.supprimer_tache(index)
        elif choix == "5":
            print("Au revoir !")
            break
        else:
            print("Option invalide. Veuillez choisir entre 1 et 5.")

if __name__ == "__main__":
    main()

Projet 3 : Jeu de devinette

import random

def jeu_devinette():
    """Jeu où l'utilisateur doit deviner un nombre aléatoire."""
    print("===== Jeu de Devinette =====")
    print("Je pense à un nombre entre 1 et 100.")
    print("Essayez de le deviner en un minimum d'essais !")
    
    # Générer un nombre aléatoire entre 1 et 100
    nombre_secret = random.randint(1, 100)
    essais = 0
    meilleur_score = float('inf')
    
    while True:
        # Demander un nombre à l'utilisateur
        try:
            essai = int(input("\nVotre proposition (ou 0 pour quitter) : "))
            
            # Vérifier si l'utilisateur veut quitter
            if essai == 0:
                print(f"Le nombre secret était {nombre_secret}.")
                print("Merci d'avoir joué !")
                break
            
            # Incrémenter le compteur d'essais
            essais += 1
            
            # Comparer avec le nombre secret
            if essai < nombre_secret:
                print("Trop petit ! Essayez un nombre plus grand.")
            elif essai > nombre_secret:
                print("Trop grand ! Essayez un nombre plus petit.")
            else:
                print(f"Bravo ! Vous avez trouvé le nombre {nombre_secret} en {essais} essais.")
                
                # Vérifier si c'est un nouveau meilleur score
                if essais < meilleur_score:
                    meilleur_score = essais
                    print("C'est votre nouveau meilleur score !")
                
                # Demander si l'utilisateur veut rejouer
                rejouer = input("Voulez-vous rejouer ? (o/n) : ")
                if rejouer.lower() != 'o':
                    print("Merci d'avoir joué !")
                    break
                
                # Réinitialiser le jeu
                nombre_secret = random.randint(1, 100)
                essais = 0
                print("\n===== Nouvelle Partie =====")
                print("Je pense à un nouveau nombre entre 1 et 100.")
                
        except ValueError:
            print("Veuillez entrer un nombre valide.")

# Lancer le jeu
jeu_devinette()

Bonnes pratiques

Style de code (PEP 8)

PEP 8 est le guide de style officiel pour le code Python. Voici quelques règles importantes :

  1. Indentation : Utilisez 4 espaces par niveau d'indentation (pas de tabulations).

  2. Longueur de ligne : Limitez les lignes à 79 caractères.

  3. Lignes vides :

    • Entourez les fonctions et classes de deux lignes vides.
    • Séparez les méthodes de classe par une ligne vide.
  4. Importations :

    • Une importation par ligne.
    • Groupez les importations dans l'ordre : bibliothèque standard, bibliothèques tierces, modules locaux.
    • Séparez chaque groupe par une ligne vide.
  5. Espaces :

    • Pas d'espaces autour des parenthèses, crochets ou accolades : f(x), pas f ( x ).
    • Un espace après les virgules : a, b, c, pas a,b,c.
    • Un espace autour des opérateurs : x = 1, pas x=1.
  6. Nommage :

    • snake_case pour les fonctions et variables.
    • PascalCase pour les classes.
    • MAJUSCULES_AVEC_UNDERSCORE pour les constantes.
    • Préfixez les attributs privés avec un underscore : _attribut_prive.

Documentation

La bonne documentation de votre code est essentielle :

  1. Docstrings : Utilisez les docstrings pour documenter les modules, classes et fonctions.

    def calculer_moyenne(nombres):
        """
        Calcule la moyenne d'une liste de nombres.
        
        Args:
            nombres (list): Liste de nombres.
            
        Returns:
            float: La moyenne des nombres.
            
        Raises:
            ValueError: Si la liste est vide.
            TypeError: Si un élément n'est pas un nombre.
        """
        if not nombres:
            raise ValueError("La liste ne peut pas être vide")
        
        return sum(nombres) / len(nombres)
    
  2. Commentaires : Utilisez des commentaires pour expliquer le "pourquoi" plutôt que le "comment".

    # Incorrect
    x = x + 1  # Incrémente x
    
    # Correct
    x = x + 1  # Compense le décalage d'index qui commence à 0
    

Tests unitaires

Les tests unitaires sont essentiels pour garantir la qualité de votre code :

import unittest

def addition(a, b):
    return a + b

class TestAddition(unittest.TestCase):
    def test_addition_positifs(self):
        self.assertEqual(addition(1, 2), 3)
    
    def test_addition_negatifs(self):
        self.assertEqual(addition(-1, -2), -3)
    
    def test_addition_mixte(self):
        self.assertEqual(addition(-1, 2), 1)

if __name__ == '__main__':
    unittest.main()

Gestion de projet avec Git

Git est un système de contrôle de version essentiel pour la gestion de code :

  1. Initialiser un dépôt :

    git init
    
  2. Ajouter des fichiers :

    git add fichier.py
    git add .  # Ajoute tous les fichiers
    
  3. Créer un commit :

    git commit -m "Message de commit descriptif"
    
  4. Gérer des branches :

    git branch nouvelle-fonctionnalite
    git checkout nouvelle-fonctionnalite
    # ou en une seule commande
    git checkout -b nouvelle-fonctionnalite
    
  5. Fusionner des branches :

    git checkout main
    git merge nouvelle-fonctionnalite
    

Structure de projet recommandée

Voici une structure de projet Python typique :

mon_projet/
│
├── README.md               # Documentation du projet
├── requirements.txt        # Dépendances du projet
├── setup.py                # Script d'installation
│
├── mon_package/            # Package principal
│   ├── __init__.py         # Marque le répertoire comme package
│   ├── module1.py          # Module du package
│   ├── module2.py
│   └── sous_package/       # Sous-package
│       ├── __init__.py
│       └── module3.py
│
├── tests/                  # Tests unitaires
│   ├── __init__.py
│   ├── test_module1.py
│   └── test_module2.py
│
├── docs/                   # Documentation
│   └── index.md
│
└── examples/               # Exemples d'utilisation
    └── exemple1.py

Ressources complémentaires

Livres recommandés

  1. "Python Crash Course" par Eric Matthes
  2. "Fluent Python" par Luciano Ramalho
  3. "Automate the Boring Stuff with Python" par Al Sweigart
  4. "Python Cookbook" par David Beazley et Brian K. Jones
  5. "Effective Python" par Brett Slatkin

Sites web et tutoriels

  1. Documentation officielle Python
  2. Real Python - Tutoriels approfondis
  3. Python.org - Site officiel
  4. PyPI (Python Package Index) - Dépôt de packages Python
  5. DataCamp - Cours interactifs
  6. Codecademy - Cours interactifs

Forums et communautés

  1. Stack Overflow - Questions et réponses
  2. Reddit r/Python - Communauté Python
  3. Discord Python - Discussions en temps réel
  4. Python Forum - Forum dédié à Python

Outils de développement recommandés

  1. IDE : PyCharm, Visual Studio Code avec l'extension Python
  2. Outils de qualité de code : flake8, pylint, black
  3. Gestion des dépendances : pip, virtualenv, pipenv, Poetry
  4. Tests : pytest, unittest
  5. Documentation : Sphinx

Conclusion

Félicitations ! Vous venez de parcourir un guide complet sur la programmation Python pour débutants. Nous avons couvert les concepts fondamentaux comme les variables, les structures de contrôle et les fonctions, puis avancé vers des sujets plus complexes comme la programmation orientée objet et l'utilisation de modules avancés.

Python est un langage puissant et polyvalent qui peut être utilisé dans pratiquement tous les domaines de l'informatique moderne. Sa syntaxe claire et sa vaste communauté en font un excellent choix pour les débutants en programmation.

N'oubliez pas que la programmation s'apprend par la pratique. Essayez de créer vos propres projets, même simples, car c'est en codant régulièrement que vous développerez vos compétences. N'hésitez pas à consulter la documentation, poser des questions sur les forums et explorer les bibliothèques qui correspondent à vos centres d'intérêt.

Bonne continuation dans votre apprentissage de Python !

Read more