Create New Document

The title of your document (will be displayed as H1)
URL-friendly name (no spaces, use dashes)
Path where to create document (optional, use forward slashes to create subdirectories)

Move/Rename Document

Current location of the document
New path for the document (including the slug)
This only changes the document's path. It does not modify the document's title (H1 heading).

Delete Document

Are you sure you want to delete this document? This action cannot be undone.

Warning: If this is a folder, all contents including subfolders and documents will be deleted.

Message

Message content goes here.

Confirm Action

Are you sure?

Attachments

Allowed file types: jpg, jpeg, png, gif, svg, webp, txt, log, csv, sfd, zip, pdf, docx, xlsx, pptx, mp4 (Max: 10MB)

Document Files

Loading attached files...

Document History

Previous Versions

Loading versions...

Preview

Select a version to preview

Wiki Settings

Language for the user interface
Number of versions to keep per document. Set to 0 to disable versioning.
Maximum allowed file size for uploads in MB.

User Management

Add New User

Leave empty to keep current password
Users with these groups can access restricted sections.

Define path-based access rules for sections of your wiki, then assign users to groups in the Users tab. Rules are evaluated in order. First match wins.

Active Rules

Import markdown files from a ZIP archive. Files will be processed and stored in the appropriate document structure. Directory structure in the ZIP (category/subcategory) will be preserved in the wiki.

Upload a ZIP file containing markdown (.md) files to import.

Create and manage backups of your wiki data. Backups include all documents, images, and configuration files.

Available Backups

Loading backups...

Add/Edit Access Rule

Selected: /

Add Column

ര# 🐍 Cours Complet de Python — De Zéro à Scripteur Autonome

Auteur : GitHub Copilot
Public visé : Débutants complets qui souhaitent apprendre Python pour scripter, automatiser des tâches, et poser des bases solides en programmation.
Niveau : Débutant à Intermédiaire
Durée estimée : 30 à 60 heures de pratique


📑 Table des matières

  1. Introduction à Python
  2. Installation et configuration de l'environnement
  3. Premier programme et syntaxe générale
  4. Variables et types de données
  5. Opérateurs
  6. Les chaînes de caractères en profondeur
  7. Les structures conditionnelles
  8. Les boucles
  9. Les fonctions
  10. Les collections (listes, tuples, dictionnaires, ensembles)
  11. La compréhension de listes et expressions génératrices
  12. Les modules et les packages
  13. La gestion des fichiers
  14. La gestion des exceptions
  15. La programmation orientée objet (POO)
  16. Les itérateurs et les générateurs
  17. Les décorateurs
  18. Le scripting (arguments, environnement, exécution)
  19. Les expressions régulières
  20. Les bonnes pratiques (PEP 8, virtualenv, pip, typage)
  21. Mini‑projets de fin de cours

1. 🎯 Introduction à Python

1.1 Qu'est‑ce que Python ?

Python est un langage de programmation interprété, multi‑paradigme (orienté objet,
procédural, fonctionnel), typé dynamiquement et fortement typé. Il a été créé
par Guido van Rossum en 1991. Son nom vient de la troupe humoristique britannique
Monty Python, et non du serpent.

Aujourd'hui, Python est l'un des langages les plus utilisés dans le monde, notamment dans :

1.2 Pourquoi choisir Python ?

1.3 Python 2 vs Python 3

Python 2 n'est plus maintenu depuis le 1er janvier 2020. Tout au long de ce cours,
nous utiliserons Python 3 (à partir de la version 3.10, mais 3.8+ devrait suffire
pour la plupart des exemples).

1.4 Compilé vs interprété

Python est interprété : votre code source .py est lu ligne par ligne par
l'interpréteur Python (souvent appelé CPython, écrit en C). En réalité, Python
compile d'abord votre code en bytecode (.pyc), puis ce bytecode est exécuté par
la Python Virtual Machine (PVM). Mais cette compilation est transparente pour vous.


2. 🛠️ Installation et configuration

2.1 Installation de Python

Sur Windows

  1. Rendez‑vous sur python.org/downloads.
  2. Téléchargez la dernière version stable (3.12 au moment de l'écriture).
  3. TRÈS IMPORTANT : cochez la case « Add Python to PATH » lors de l'installation.
  4. Cliquez sur Install Now.

Pour vérifier que tout fonctionne, ouvrez un terminal (cmd ou PowerShell) :

python --version

Vous devriez voir quelque chose comme Python 3.12.1.

Sur macOS

brew install python

Sur Linux (Debian/Ubuntu)

sudo apt update
sudo apt install python3 python3-pip python3-venv

2.2 Choisir un éditeur de code

Plusieurs choix s'offrent à vous :

Pour ce cours, j'utiliserai VS Code avec l'extension officielle Python de Microsoft.

2.3 L'interpréteur interactif (REPL)

Tapez simplement python dans un terminal :

Python 3.12.1 (main, Dec  7 2023, 12:00:00)
Type "help", "copyright", "credits" or "license" for more information.
>>>

Le >>> est l'invite (prompt). Vous pouvez taper du code Python directement :

>>> 2 + 2
4
>>> print("Bonjour")
Bonjour
>>> exit()

Pour quitter : exit() ou Ctrl+Z puis Entrée (Windows), ou Ctrl+D (Linux/Mac).

2.4 Exécuter un script

Créez un fichier hello.py :

print("Hello, World!")

Puis dans un terminal :

python hello.py

3. 📝 Premier programme et syntaxe générale

3.1 Le sacro‑saint « Hello, World! »

print("Hello, World!")

print() est une fonction intégrée (built‑in) qui affiche du texte dans la console.
Les guillemets (" ou ') délimitent une chaîne de caractères.

3.2 Les commentaires

Les commentaires sont ignorés par l'interpréteur. Ils servent à expliquer le code.

# Ceci est un commentaire sur une ligne

"""
Ceci est un commentaire
sur plusieurs lignes
(en réalité, c'est une chaîne non assignée).
"""

x = 10  # Commentaire en fin de ligne

3.3 L'indentation : la signature de Python

En Python, l'indentation n'est pas décorative, elle est syntaxique.
On utilise 4 espaces par niveau (jamais de tabulations mélangées).

if True:
    print("Indenté de 4 espaces")
    if True:
        print("Indenté de 8 espaces")
print("Plus indenté")

Une mauvaise indentation provoque une IndentationError.

3.4 Les instructions multiples

Une instruction par ligne, normalement. On peut en mettre plusieurs avec ; mais c'est
fortement déconseillé :

x = 1; y = 2; z = 3   # À éviter

Pour couper une ligne longue, on utilise le backslash \ ou les parenthèses :

total = 1 + 2 + 3 + \
        4 + 5 + 6

total = (1 + 2 + 3 +
         4 + 5 + 6)

3.5 Les mots‑clés réservés

Python possède une trentaine de mots‑clés réservés que vous ne pouvez pas utiliser
comme noms de variables :

False    None     True     and      as       assert   async    await
break    class    continue def      del      elif     else     except
finally  for      from     global   if       import   in       is
lambda   nonlocal not      or       pass     raise    return   try
while    with     yield

Pour les voir dans votre interpréteur :

import keyword
print(keyword.kwlist)

4. 📦 Variables et types de données

4.1 Qu'est‑ce qu'une variable ?

Une variable est un nom qui pointe vers une valeur stockée en mémoire.
En Python, on n'a pas besoin de déclarer le type : il est déduit automatiquement.

age = 25            # int
prix = 19.99        # float
nom = "Alice"       # str
est_majeur = True   # bool

4.2 Règles de nommage

ma_variable = 10        # ✅ Bon
maVariable = 10         # ❌ Style Java, à éviter en Python
2chats = "Tom et Jerry" # ❌ Erreur : commence par un chiffre
_privé = "ok"           # ✅ Underscore en début = convention "privé"

4.3 Affectation multiple

a, b, c = 1, 2, 3
x = y = z = 0
a, b = b, a   # Échange (swap) de variables, élégant !

4.4 Les types de base

4.4.1 Les entiers (int)

n = 42
grand = 10**100         # Pas de limite, sauf la mémoire
binaire = 0b1010        # = 10
octal = 0o17            # = 15
hexa = 0xFF             # = 255

4.4.2 Les flottants (float)

pi = 3.14159
e = 2.718
notation_sci = 1.5e3    # = 1500.0
infini = float('inf')
pas_un_nombre = float('nan')

⚠️ Les flottants sont stockés en binaire IEEE 754 → imprécisions :

>>> 0.1 + 0.2
0.30000000000000004

Pour des calculs précis (finance), utilisez le module decimal.

4.4.3 Les booléens (bool)

vrai = True
faux = False

En interne : True == 1, False == 0.

4.4.4 Les chaînes (str)

prenom = "Alice"
nom = 'Dupont'
phrase = """Une chaîne
sur plusieurs lignes"""

4.4.5 Le type NoneType

None représente l'absence de valeur (équivalent du null d'autres langages).

resultat = None

4.5 Connaître et convertir les types

type(42)         # <class 'int'>
type("hello")    # <class 'str'>
type(3.14)       # <class 'float'>

int("42")        # 42
float("3.14")    # 3.14
str(42)          # "42"
bool(0)          # False
bool("a")        # True (toute chaîne non vide est True)
list("abc")      # ['a', 'b', 'c']

4.6 Saisie utilisateur

nom = input("Quel est ton nom ? ")
print(f"Bonjour, {nom} !")

age = int(input("Quel est ton âge ? "))   # Conversion obligatoire
print(f"Dans 10 ans, tu auras {age + 10} ans.")

input() retourne toujours une chaîne, même si l'utilisateur tape un nombre.


5. ➕ Les opérateurs

5.1 Opérateurs arithmétiques

Opérateur Description Exemple Résultat
+ Addition 5 + 3 8
- Soustraction 5 - 3 2
* Multiplication 5 * 3 15
/ Division 7 / 2 3.5
// Division entière 7 // 2 3
% Modulo 7 % 2 1
** Puissance 2 ** 10 1024
print(17 / 5)    # 3.4
print(17 // 5)   # 3 (quotient entier)
print(17 % 5)    # 2 (reste)
print(2 ** 8)    # 256

5.2 Opérateurs de comparaison

Opérateur Signification
== Égal à
!= Différent de
< Strictement inférieur
> Strictement supérieur
<= Inférieur ou égal
>= Supérieur ou égal

Ils retournent un bool :

print(5 == 5)      # True
print(5 != 3)      # True
print("a" < "b")   # True (ordre lexicographique)

5.3 Opérateurs logiques

True and False    # False
True or False     # True
not True          # False

Python utilise l'évaluation paresseuse (short‑circuit) :

def f():
    print("appelé")
    return True

True or f()     # f() n'est PAS appelée
False and f()   # f() n'est PAS appelée

5.4 Opérateurs d'affectation composés

x = 10
x += 5    # x = x + 5  → 15
x -= 3    # x = x - 3  → 12
x *= 2    # x = x * 2  → 24
x /= 4    # x = x / 4  → 6.0
x //= 2   # x = x // 2 → 3.0
x **= 2   # x = x ** 2 → 9.0
x %= 4    # x = x % 4  → 1.0

5.5 Opérateurs d'identité et d'appartenance

# is / is not : compare l'identité (même objet en mémoire)
a = [1, 2, 3]
b = [1, 2, 3]
c = a
print(a == b)   # True (même contenu)
print(a is b)   # False (objets différents)
print(a is c)   # True (même objet)

# in / not in : appartenance
print(3 in [1, 2, 3])        # True
print("a" in "chat")         # True
print("z" not in "chat")     # True

5.6 Priorité des opérateurs

Du plus prioritaire au moins prioritaire (extrait) :

  1. **
  2. +x, -x (unaire), ~x
  3. *, /, //, %
  4. +, -
  5. Comparaisons (<, <=, >, >=, !=, ==)
  6. not
  7. and
  8. or

En cas de doute → parenthèses ! Elles rendent le code plus clair.

print(2 + 3 * 4)        # 14
print((2 + 3) * 4)      # 20

6. 🔤 Les chaînes de caractères en profondeur

6.1 Création

s1 = "double"
s2 = 'simple'
s3 = "L'apostrophe ne pose pas de problème"
s4 = 'Il a dit "bonjour"'
s5 = """Multi‑
ligne"""
s6 = "Ligne 1\nLigne 2"   # \n = saut de ligne

6.2 Caractères spéciaux (échappement)

Séquence Signification
\n Saut de ligne
\t Tabulation
\\ Backslash
\" Guillemet double
\' Apostrophe
\u00e9 Caractère Unicode (é)

Pour ignorer les échappements (utile pour les chemins Windows ou les regex) :

chemin = r"C:\Users\Alice\Documents"   # raw string

6.3 Concaténation et répétition

salut = "Hello, " + "World!"
ligne = "-" * 30                       # "------------------------------"

6.4 Indexation et tranches (slicing)

Une chaîne est une séquence. Chaque caractère a un index, à partir de 0.

s = "Python"
#    0 1 2 3 4 5
#   -6-5-4-3-2-1

print(s[0])       # 'P'
print(s[-1])      # 'n'
print(s[1:4])     # 'yth'   (de l'index 1 inclus à 4 exclu)
print(s[:3])      # 'Pyt'
print(s[3:])      # 'hon'
print(s[::2])     # 'Pto'   (un caractère sur deux)
print(s[::-1])    # 'nohtyP' (chaîne inversée)

⚠️ Les chaînes sont immuables : s[0] = "Q" provoque une erreur.

6.5 Les méthodes de chaînes

s = "  Bonjour le Monde  "

s.upper()              # "  BONJOUR LE MONDE  "
s.lower()              # "  bonjour le monde  "
s.title()              # "  Bonjour Le Monde  "
s.strip()              # "Bonjour le Monde"
s.lstrip()             # "Bonjour le Monde  "
s.rstrip()             # "  Bonjour le Monde"
s.replace("Monde", "Python")
s.split()              # ['Bonjour', 'le', 'Monde']
s.split("o")           # ['  B', 'nj', 'ur le M', 'nde  ']
"-".join(["a", "b", "c"])    # "a-b-c"
s.startswith("  Bon") # True
s.endswith("de  ")    # True
s.find("le")          # 9 (index, ou -1 si non trouvé)
s.count("o")          # 3
s.isdigit()           # False
"123".isdigit()       # True
"abc".isalpha()       # True
"abc123".isalnum()    # True
len(s)                # 20

6.6 Le formatage de chaînes

6.6.1 f‑strings (recommandé, Python 3.6+)

nom = "Alice"
age = 30
print(f"Je m'appelle {nom} et j'ai {age} ans.")
print(f"L'an prochain, j'aurai {age + 1} ans.")
print(f"{3.14159:.2f}")              # 3.14
print(f"{1000000:,}")                # 1,000,000
print(f"{42:>10}")                   # alignement à droite sur 10 caractères
print(f"{42:<10}|")                  # alignement à gauche
print(f"{42:^10}")                   # centré
print(f"{42:08d}")                   # 00000042

6.6.2 La méthode .format()

"Je m'appelle {} et j'ai {} ans.".format(nom, age)
"{0} {1} {0}".format("ha", "hi")     # "ha hi ha"
"{nom} a {age} ans".format(nom="Bob", age=20)

6.6.3 L'ancien style % (à éviter dans le code moderne)

"%s a %d ans" % (nom, age)

7. 🔀 Les structures conditionnelles

7.1 if / elif / else

age = 18

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

7.2 Conditions composées

note = 14
present = True

if note >= 10 and present:
    print("Validé")

if note < 5 or not present:
    print("Échec")

7.3 Valeurs truthy et falsy

En Python, beaucoup de valeurs sont considérées comme fausses dans un contexte
booléen :

Tout le reste est truthy.

if []:
    print("Liste non vide")   # Ne s'affiche pas
else:
    print("Liste vide")       # ✅

7.4 L'opérateur ternaire

age = 20
statut = "majeur" if age >= 18 else "mineur"

7.5 Le match (Python 3.10+)

Équivalent du switch d'autres langages, en plus puissant :

def décrire(jour):
    match jour:
        case "lundi" | "mardi" | "mercredi" | "jeudi" | "vendredi":
            return "Semaine"
        case "samedi" | "dimanche":
            return "Week‑end"
        case _:
            return "Inconnu"

8. 🔁 Les boucles

8.1 La boucle while

i = 0
while i < 5:
    print(i)
    i += 1

⚠️ Attention aux boucles infinies ! Toujours s'assurer que la condition deviendra fausse.

8.2 La boucle for

En Python, for itère sur les éléments d'une séquence ou d'un itérable.

for lettre in "Python":
    print(lettre)

for nombre in [1, 2, 3, 4, 5]:
    print(nombre)

8.3 La fonction range()

range(5)         # 0, 1, 2, 3, 4
range(2, 8)      # 2, 3, 4, 5, 6, 7
range(0, 10, 2)  # 0, 2, 4, 6, 8
range(10, 0, -1) # 10, 9, ..., 1

for i in range(5):
    print(i)

8.4 break et continue

# break : sortir de la boucle
for i in range(10):
    if i == 5:
        break
    print(i)    # 0, 1, 2, 3, 4

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

8.5 La clause else des boucles

Le else s'exécute si la boucle se termine sans break :

for n in [2, 3, 5, 7]:
    if n % 2 == 0:
        print("Pair trouvé")
        break
else:
    print("Tous impairs")

8.6 Boucles imbriquées

for i in range(1, 4):
    for j in range(1, 4):
        print(f"{i} x {j} = {i*j}")

8.7 enumerate(), zip(), reversed()

fruits = ["pomme", "banane", "kiwi"]

for i, fruit in enumerate(fruits):
    print(i, fruit)

prix = [1.0, 0.5, 2.0]
for fruit, p in zip(fruits, prix):
    print(f"{fruit} : {p} €")

for fruit in reversed(fruits):
    print(fruit)

9. 🧩 Les fonctions

9.1 Définir une fonction

def saluer(nom):
    """Affiche un message de bienvenue."""
    print(f"Bonjour, {nom} !")

saluer("Alice")

La chaîne entre triples guillemets est appelée docstring : elle documente la fonction.

9.2 Retourner une valeur

def carre(x):
    return x * x

resultat = carre(5)   # 25

Une fonction sans return retourne implicitement None.

9.3 Plusieurs valeurs de retour

def min_max(liste):
    return min(liste), max(liste)

mini, maxi = min_max([3, 1, 4, 1, 5, 9, 2, 6])

En réalité, on retourne un tuple.

9.4 Arguments par défaut

def saluer(nom, salutation="Bonjour"):
    print(f"{salutation}, {nom} !")

saluer("Alice")               # Bonjour, Alice !
saluer("Bob", "Salut")        # Salut, Bob !
saluer(nom="Carol")           # Bonjour, Carol !

⚠️ Piège : ne jamais utiliser de valeur mutable comme défaut !

def ajouter(item, liste=[]):     # ❌ DANGER
    liste.append(item)
    return liste

print(ajouter(1))   # [1]
print(ajouter(2))   # [1, 2]  ← La liste est partagée !

def ajouter(item, liste=None):   # ✅ Bonne pratique
    if liste is None:
        liste = []
    liste.append(item)
    return liste

9.5 Arguments positionnels et nommés

def présenter(prenom, nom, age):
    print(f"{prenom} {nom}, {age} ans")

présenter("Alice", "Dupont", 30)               # positionnel
présenter(age=30, prenom="Alice", nom="Dupont") # nommé

9.6 *args et **kwargs

def somme(*nombres):
    """Accepte un nombre variable d'arguments positionnels."""
    return sum(nombres)

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

def afficher_infos(**infos):
    """Accepte un nombre variable d'arguments nommés."""
    for cle, valeur in infos.items():
        print(f"{cle} : {valeur}")

afficher_infos(nom="Alice", age=30, ville="Paris")

On peut combiner les quatre types d'arguments :

def fonction(a, b, *args, option=True, **kwargs):
    ...

9.7 Portée des variables (scope)

Python suit la règle LEGB : Local → Enclosing → Global → Built‑in.

x = "global"

def externe():
    x = "enclosing"
    def interne():
        x = "local"
        print(x)    # local
    interne()
    print(x)        # enclosing

externe()
print(x)            # global

Les mots‑clés global et nonlocal permettent de modifier des variables externes :

compteur = 0

def incrementer():
    global compteur
    compteur += 1

incrementer()
incrementer()
print(compteur)   # 2

9.8 Les fonctions lambda

Fonctions anonymes, sur une ligne :

carre = lambda x: x ** 2
print(carre(4))   # 16

# Très utile avec sorted, map, filter
points = [(1, 3), (5, 1), (2, 7)]
points.sort(key=lambda p: p[1])

9.9 Fonctions comme objets

En Python, les fonctions sont des objets de première classe : on peut les passer
en argument, les retourner, les stocker dans des variables.

def double(x): return x * 2
def triple(x): return x * 3

operations = [double, triple]
for op in operations:
    print(op(5))   # 10, puis 15

9.10 map, filter, reduce

nombres = [1, 2, 3, 4, 5]

doubles = list(map(lambda x: x * 2, nombres))
pairs = list(filter(lambda x: x % 2 == 0, nombres))

from functools import reduce
total = reduce(lambda a, b: a + b, nombres)   # 15

10. 📚 Les collections

10.1 Les listes

Les listes sont des séquences ordonnées et mutables.

10.1.1 Création

vide = []
nombres = [1, 2, 3, 4, 5]
mixte = [1, "deux", 3.0, True, None]
nestée = [[1, 2], [3, 4], [5, 6]]
liste = list(range(10))

10.1.2 Accès et modification

fruits = ["pomme", "banane", "kiwi"]
print(fruits[0])       # pomme
print(fruits[-1])      # kiwi

fruits[1] = "fraise"
print(fruits)          # ['pomme', 'fraise', 'kiwi']

# Slicing comme pour les chaînes
print(fruits[0:2])     # ['pomme', 'fraise']
print(fruits[::-1])    # liste inversée

10.1.3 Méthodes principales

liste = [3, 1, 4, 1, 5]

liste.append(9)        # [3, 1, 4, 1, 5, 9]
liste.insert(0, 99)    # [99, 3, 1, 4, 1, 5, 9]
liste.extend([2, 6])   # [99, 3, 1, 4, 1, 5, 9, 2, 6]
liste.remove(1)        # supprime le PREMIER 1
liste.pop()            # supprime et retourne le dernier
liste.pop(0)           # supprime et retourne celui d'index 0
liste.index(4)         # 1 (position de la première occurrence)
liste.count(1)         # 1
liste.sort()           # trie sur place (croissant)
liste.sort(reverse=True)
liste.reverse()        # inverse sur place
liste.clear()          # vide la liste
copie = liste.copy()   # copie superficielle

10.1.4 Tri non destructif : sorted()

liste = [3, 1, 4, 1, 5]
nouvelle = sorted(liste)              # liste inchangée
décroissant = sorted(liste, reverse=True)
mots = sorted(["banane", "abricot"], key=len)

10.1.5 Concaténation et répétition

[1, 2] + [3, 4]      # [1, 2, 3, 4]
[0] * 5              # [0, 0, 0, 0, 0]

10.1.6 ⚠️ Copie vs référence

a = [1, 2, 3]
b = a              # b pointe vers la MÊME liste
b.append(4)
print(a)           # [1, 2, 3, 4] !

c = a.copy()       # ou list(a), ou a[:]
c.append(5)
print(a)           # [1, 2, 3, 4]  (inchangé)

Pour copier en profondeur (listes imbriquées) :

import copy
deep = copy.deepcopy(a)

10.2 Les tuples

Les tuples sont comme les listes, mais immuables.

point = (3, 4)
solo = (5,)            # ⚠️ la virgule est obligatoire pour un singleton
sans_paren = 1, 2, 3   # tuple aussi !

x, y = point           # déballage (unpacking)
print(point[0])        # 3

# point[0] = 10        # ❌ TypeError

Avantages des tuples :

10.3 Les dictionnaires

Structure clé/valeur (équivalent des « hash maps »).

10.3.1 Création et accès

personne = {
    "nom": "Dupont",
    "prenom": "Alice",
    "age": 30
}

print(personne["nom"])           # Dupont
print(personne.get("email"))     # None (pas d'erreur)
print(personne.get("email", "N/A"))   # "N/A"

personne["email"] = "alice@ex.fr"   # ajout / modification
del personne["age"]                  # suppression

10.3.2 Itération

for cle in personne:
    print(cle)

for cle, valeur in personne.items():
    print(f"{cle} = {valeur}")

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

10.3.3 Méthodes utiles

personne.keys()
personne.values()
personne.items()
personne.update({"ville": "Paris", "age": 31})
personne.pop("ville")
personne.setdefault("pays", "France")
"nom" in personne                 # True
len(personne)
personne.clear()

10.3.4 Dictionnaires imbriqués

contacts = {
    "alice": {"tel": "0102", "email": "a@x.fr"},
    "bob":   {"tel": "0304", "email": "b@x.fr"},
}
print(contacts["alice"]["email"])

10.4 Les ensembles (set)

Collections non ordonnées d'éléments uniques.

fruits = {"pomme", "banane", "kiwi"}
fruits.add("fraise")
fruits.discard("banane")    # pas d'erreur si absent
fruits.remove("kiwi")       # KeyError si absent

# Élimination des doublons
nombres = [1, 2, 2, 3, 3, 3, 4]
uniques = list(set(nombres))   # [1, 2, 3, 4]

# Opérations ensemblistes
a = {1, 2, 3, 4}
b = {3, 4, 5, 6}
print(a | b)   # union          {1, 2, 3, 4, 5, 6}
print(a & b)   # intersection   {3, 4}
print(a - b)   # différence     {1, 2}
print(a ^ b)   # diff. symétrique {1, 2, 5, 6}

⚠️ Le set vide se crée avec set(), pas {} (qui est un dict vide).

10.5 Récapitulatif

Type Ordonné Mutable Doublons Indexable
list
tuple
dict ✅* clés non par clé
set

* Depuis Python 3.7, les dicts conservent l'ordre d'insertion.


11. 🚀 Compréhensions et générateurs

11.1 Compréhensions de listes

Syntaxe concise pour créer des listes :

# Approche classique
carres = []
for x in range(10):
    carres.append(x ** 2)

# Compréhension équivalente
carres = [x ** 2 for x in range(10)]

Avec condition :

pairs = [x for x in range(20) if x % 2 == 0]

Avec if/else :

parite = ["pair" if x % 2 == 0 else "impair" for x in range(5)]

Imbriquée :

matrice = [[i*j for j in range(3)] for i in range(3)]
# [[0, 0, 0], [0, 1, 2], [0, 2, 4]]

11.2 Compréhensions de dictionnaires

carres = {x: x**2 for x in range(5)}
# {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

inverser = {v: k for k, v in personne.items()}

11.3 Compréhensions d'ensembles

voyelles = {c for c in "Hello, World!" if c.lower() in "aeiou"}

11.4 Expressions génératrices

Comme les compréhensions, mais avec des () : elles produisent les valeurs à la demande
(lazy), donc plus économes en mémoire.

gen = (x ** 2 for x in range(1_000_000))
print(sum(gen))   # Calcule sans stocker un million de carrés en mémoire

12. 📦 Modules et packages

12.1 Importer un module

import math
print(math.pi)
print(math.sqrt(16))

import math as m       # alias
from math import pi, sqrt
from math import *     # ⚠️ déconseillé (pollue le namespace)

12.2 Créer son propre module

Fichier mes_outils.py :

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

PI = 3.14159

Fichier main.py (dans le même dossier) :

import mes_outils
print(mes_outils.saluer("Alice"))
print(mes_outils.PI)

12.3 Le bloc if __name__ == "__main__"

def main():
    print("Programme principal")

if __name__ == "__main__":
    main()

Ce bloc ne s'exécute que si le fichier est lancé directement (pas s'il est importé).

12.4 Les packages

Un package = un dossier contenant un fichier __init__.py (qui peut être vide).

mon_package/
    __init__.py
    module1.py
    module2.py
from mon_package import module1
from mon_package.module2 import ma_fonction

12.5 La bibliothèque standard (sélection)

Module Utilité
os Système d'exploitation, fichiers
sys Interpréteur, arguments
pathlib Manipulation moderne de chemins
datetime Dates et heures
time Pauses, mesures de temps
math Fonctions mathématiques
random Aléatoire
json Parser et écrire du JSON
csv Lire/écrire des CSV
re Expressions régulières
collections Collections avancées (Counter, deque, …)
itertools Outils pour itérateurs
functools Outils pour fonctions
subprocess Lancer des commandes système
argparse Parser des arguments en ligne de commande
logging Journalisation
urllib Téléchargement HTTP basique
sqlite3 Base de données SQLite

Exemples :

import os
print(os.getcwd())                  # dossier courant
print(os.listdir("."))              # contenu du dossier

import random
print(random.randint(1, 10))
print(random.choice(["a", "b", "c"]))
random.shuffle([1, 2, 3, 4])

import datetime
maintenant = datetime.datetime.now()
print(maintenant.strftime("%d/%m/%Y %H:%M"))

import time
debut = time.time()
time.sleep(1)
print(f"Écoulé : {time.time() - debut:.3f} s")

12.6 Installer des paquets externes avec pip

pip install requests
pip install --upgrade pandas
pip uninstall numpy
pip list
pip freeze > requirements.txt
pip install -r requirements.txt

13. 📁 Gestion des fichiers

13.1 Ouvrir et lire un fichier

fichier = open("texte.txt", "r", encoding="utf-8")
contenu = fichier.read()
fichier.close()

⚠️ Toujours fermer un fichier. La meilleure pratique est d'utiliser with :

with open("texte.txt", "r", encoding="utf-8") as f:
    contenu = f.read()
# Le fichier est fermé automatiquement à la sortie du bloc

13.2 Modes d'ouverture

Mode Description
"r" Lecture (par défaut). Erreur si le fichier n'existe pas
"w" Écriture. Écrase le fichier existant
"a" Ajout (append) à la fin
"x" Création exclusive (erreur si existe)
"b" Binaire (à combiner : "rb", "wb")
"t" Texte (par défaut)
"+" Lecture et écriture ("r+", "w+")

13.3 Lire ligne par ligne

with open("texte.txt", encoding="utf-8") as f:
    for ligne in f:
        print(ligne.rstrip())   # rstrip pour retirer le \n

# Ou bien
with open("texte.txt", encoding="utf-8") as f:
    lignes = f.readlines()      # liste de lignes

13.4 Écrire dans un fichier

with open("sortie.txt", "w", encoding="utf-8") as f:
    f.write("Première ligne\n")
    f.write("Deuxième ligne\n")
    f.writelines(["Trois\n", "Quatre\n"])

13.5 Le module pathlib (moderne)

from pathlib import Path

p = Path("dossier/fichier.txt")
print(p.exists())
print(p.is_file())
print(p.parent)             # dossier
print(p.name)               # fichier.txt
print(p.stem)               # fichier
print(p.suffix)             # .txt
print(p.absolute())

# Lire / écrire en une ligne
texte = p.read_text(encoding="utf-8")
p.write_text("nouveau contenu", encoding="utf-8")

# Parcourir un dossier
for fichier in Path(".").glob("*.py"):
    print(fichier)

# Récursivement
for fichier in Path(".").rglob("*.txt"):
    print(fichier)

13.6 JSON

import json

data = {"nom": "Alice", "âge": 30, "loisirs": ["lecture", "vélo"]}

# Écrire
with open("data.json", "w", encoding="utf-8") as f:
    json.dump(data, f, ensure_ascii=False, indent=2)

# Lire
with open("data.json", encoding="utf-8") as f:
    chargé = json.load(f)

# Conversions chaîne ↔ dict
texte = json.dumps(data)
parsed = json.loads(texte)

13.7 CSV

import csv

# Écrire
with open("personnes.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.writer(f)
    writer.writerow(["nom", "âge"])
    writer.writerow(["Alice", 30])
    writer.writerow(["Bob", 25])

# Lire
with open("personnes.csv", encoding="utf-8") as f:
    reader = csv.reader(f)
    for ligne in reader:
        print(ligne)

# Avec dictionnaires
with open("personnes.csv", encoding="utf-8") as f:
    reader = csv.DictReader(f)
    for ligne in reader:
        print(ligne["nom"], ligne["âge"])

14. ⚠️ La gestion des exceptions

14.1 Pourquoi gérer les exceptions ?

Une exception non gérée fait planter le programme. Les exceptions permettent de
réagir aux erreurs au lieu de subir.

14.2 try / except

try:
    x = int(input("Un nombre : "))
    print(10 / x)
except ValueError:
    print("Ce n'est pas un nombre valide.")
except ZeroDivisionError:
    print("On ne divise pas par zéro.")
except Exception as e:
    print(f"Erreur inattendue : {e}")

14.3 else et finally

try:
    f = open("data.txt")
except FileNotFoundError:
    print("Fichier introuvable")
else:
    # exécuté seulement si AUCUNE exception n'a eu lieu
    print(f.read())
    f.close()
finally:
    # exécuté DANS TOUS LES CAS
    print("Nettoyage terminé")

14.4 Hiérarchie des exceptions courantes

BaseException
 └── Exception
      ├── ArithmeticError
      │    └── ZeroDivisionError
      ├── LookupError
      │    ├── IndexError
      │    └── KeyError
      ├── ValueError
      ├── TypeError
      ├── FileNotFoundError
      ├── OSError
      └── ...

Cibler une exception précise est toujours préférable.

14.5 Lever une exception

def racine_carree(x):
    if x < 0:
        raise ValueError("x doit être positif ou nul")
    return x ** 0.5

14.6 Créer ses propres exceptions

class SoldeInsuffisantError(Exception):
    """Levée quand un compte n'a pas assez de fonds."""

def retirer(compte, montant):
    if montant > compte["solde"]:
        raise SoldeInsuffisantError("Manque de fonds")
    compte["solde"] -= montant

15. 🏛️ La programmation orientée objet

15.1 Concepts

15.2 Définir une classe

class Personne:
    """Représente une personne."""

    # Attribut de classe (partagé)
    espece = "Homo sapiens"

    def __init__(self, nom, age):
        # Attributs d'instance
        self.nom = nom
        self.age = age

    def se_presenter(self):
        print(f"Je m'appelle {self.nom} et j'ai {self.age} ans.")

alice = Personne("Alice", 30)
alice.se_presenter()
print(alice.nom)
print(Personne.espece)

self représente l'instance en cours. Toujours en premier paramètre des méthodes.

15.3 Méthode __init__ (constructeur)

Appelée automatiquement à la création de l'objet.

15.4 Méthodes spéciales (dunder methods)

class Vecteur:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __repr__(self):
        return f"Vecteur({self.x}, {self.y})"

    def __str__(self):
        return f"({self.x}, {self.y})"

    def __add__(self, autre):
        return Vecteur(self.x + autre.x, self.y + autre.y)

    def __eq__(self, autre):
        return self.x == autre.x and self.y == autre.y

    def __len__(self):
        return int((self.x ** 2 + self.y ** 2) ** 0.5)

v1 = Vecteur(1, 2)
v2 = Vecteur(3, 4)
print(v1 + v2)        # (4, 6)
print(v1 == Vecteur(1, 2))   # True

Quelques méthodes spéciales courantes :

Méthode Rôle
__init__ constructeur
__repr__ représentation officielle (debug)
__str__ conversion en chaîne (str())
__len__ len(obj)
__getitem__ obj[key]
__setitem__ obj[key] = ...
__iter__ itérable
__call__ rendre l'objet appelable
__eq__, __lt__, … comparaisons
__add__, __mul__, … opérateurs arithmétiques

15.5 Encapsulation et conventions

Python n'a pas de vrai private, mais des conventions :

class CompteBancaire:
    def __init__(self, solde=0):
        self._solde = solde

    def deposer(self, montant):
        if montant <= 0:
            raise ValueError("Montant invalide")
        self._solde += montant

    @property
    def solde(self):
        return self._solde

Le décorateur @property permet d'accéder à une méthode comme à un attribut :
compte.solde au lieu de compte.solde().

15.6 Héritage

class Animal:
    def __init__(self, nom):
        self.nom = nom

    def crier(self):
        print("Bruit générique")

class Chien(Animal):
    def crier(self):
        print(f"{self.nom} fait Wouf !")

class Chat(Animal):
    def __init__(self, nom, couleur):
        super().__init__(nom)        # appelle le constructeur parent
        self.couleur = couleur

    def crier(self):
        print(f"{self.nom} fait Miaou !")

rex = Chien("Rex")
rex.crier()       # Rex fait Wouf !

15.7 Polymorphisme

animaux = [Chien("Rex"), Chat("Mimi", "noir")]
for a in animaux:
    a.crier()    # Chacun crie selon sa classe

15.8 Classes abstraites

from abc import ABC, abstractmethod

class Forme(ABC):
    @abstractmethod
    def aire(self):
        ...

class Carre(Forme):
    def __init__(self, cote):
        self.cote = cote
    def aire(self):
        return self.cote ** 2

# f = Forme()    # ❌ TypeError
c = Carre(5)
print(c.aire())  # 25

15.9 Méthodes de classe et statiques

class Math:
    PI = 3.14159

    @classmethod
    def aire_disque(cls, r):
        return cls.PI * r ** 2

    @staticmethod
    def carre(x):
        return x * x

print(Math.aire_disque(2))
print(Math.carre(5))

15.10 Dataclasses (Python 3.7+)

Pour créer rapidement des classes « porteuses de données » :

from dataclasses import dataclass

@dataclass
class Point:
    x: float
    y: float

p = Point(1.0, 2.0)
print(p)              # Point(x=1.0, y=2.0)
print(p == Point(1.0, 2.0))   # True

16. 🔄 Itérateurs et générateurs

16.1 Le protocole d'itération

Un objet est itérable s'il possède une méthode __iter__() qui retourne un
itérateur (objet ayant __next__()).

liste = [1, 2, 3]
it = iter(liste)
print(next(it))   # 1
print(next(it))   # 2
print(next(it))   # 3
# next(it)        # StopIteration

16.2 Créer un itérateur

class Compteur:
    def __init__(self, max):
        self.max = max
        self.n = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.n >= self.max:
            raise StopIteration
        self.n += 1
        return self.n

for n in Compteur(3):
    print(n)   # 1, 2, 3

16.3 Les générateurs

Bien plus simples ! Une fonction qui contient yield est un générateur :

def compteur(max):
    n = 0
    while n < max:
        n += 1
        yield n

for x in compteur(5):
    print(x)

Avantage : la valeur est produite à la demande, pas stockée en mémoire.

def fibonacci():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

import itertools
for n in itertools.islice(fibonacci(), 10):
    print(n)   # 10 premiers nombres de Fibonacci

17. 🎀 Les décorateurs

Un décorateur est une fonction qui modifie une autre fonction.

17.1 Premier décorateur

def majuscule(fonction):
    def wrapper(*args, **kwargs):
        resultat = fonction(*args, **kwargs)
        return resultat.upper()
    return wrapper

@majuscule
def saluer(nom):
    return f"bonjour {nom}"

print(saluer("alice"))   # BONJOUR ALICE

@majuscule est équivalent à saluer = majuscule(saluer).

17.2 Décorateur de chronométrage

import time
from functools import wraps

def chrono(fonction):
    @wraps(fonction)
    def wrapper(*args, **kwargs):
        debut = time.perf_counter()
        resultat = fonction(*args, **kwargs)
        duree = time.perf_counter() - debut
        print(f"{fonction.__name__} a pris {duree:.4f} s")
        return resultat
    return wrapper

@chrono
def calcul_lent():
    time.sleep(1)
    return 42

calcul_lent()

@wraps préserve le nom et la docstring de la fonction originale.

17.3 Décorateurs avec paramètres

def repeter(n):
    def decorateur(fonction):
        def wrapper(*args, **kwargs):
            for _ in range(n):
                fonction(*args, **kwargs)
        return wrapper
    return decorateur

@repeter(3)
def coucou():
    print("coucou")

coucou()   # affiche 3 fois

18. 💻 Le scripting en pratique

18.1 Le shebang (Linux/Mac)

En tête de fichier :

#!/usr/bin/env python3

Puis chmod +x mon_script.py et on peut lancer ./mon_script.py.

18.2 Arguments en ligne de commande : sys.argv

import sys

print("Nom du script :", sys.argv[0])
print("Arguments :", sys.argv[1:])
python script.py foo bar 42
# Arguments : ['foo', 'bar', '42']

18.3 argparse : la solution professionnelle

import argparse

parser = argparse.ArgumentParser(description="Calcule la somme de deux nombres.")
parser.add_argument("a", type=int, help="premier nombre")
parser.add_argument("b", type=int, help="second nombre")
parser.add_argument("--produit", action="store_true",
                    help="calcule aussi le produit")

args = parser.parse_args()
print(f"Somme : {args.a + args.b}")
if args.produit:
    print(f"Produit : {args.a * args.b}")
python script.py 3 5 --produit

18.4 Variables d'environnement

import os
print(os.environ.get("PATH"))
print(os.environ.get("MA_VAR", "valeur par défaut"))
os.environ["MA_VAR"] = "hello"

18.5 Lancer des commandes système

import subprocess

# Méthode moderne (Python 3.5+)
resultat = subprocess.run(["ls", "-la"], capture_output=True, text=True)
print(resultat.stdout)
print("Code retour :", resultat.returncode)

18.6 Codes de retour

import sys

if erreur_critique:
    sys.exit(1)    # code != 0 → échec

sys.exit(0)        # succès

19. 🔍 Les expressions régulières

Module re, indispensable pour les manipulations de texte avancées.

import re

texte = "Mon numéro est 06-12-34-56-78 et l'autre 0712345678."

# Recherche
match = re.search(r"\d{2}-\d{2}-\d{2}-\d{2}-\d{2}", texte)
if match:
    print(match.group())   # 06-12-34-56-78

# Trouver toutes les occurrences
nombres = re.findall(r"\d+", texte)
print(nombres)   # ['06', '12', '34', '56', '78', '0712345678']

# Remplacement
masqué = re.sub(r"\d", "*", texte)

# Découpage
parties = re.split(r"\s+", "  hello   world  python ")

Quelques motifs essentiels :

Motif Signification
. Tout caractère sauf saut de ligne
\d Chiffre [0-9]
\D Non‑chiffre
\w Caractère « mot » (lettre, chiffre, _)
\s Espace blanc
^ / $ Début / fin de chaîne
* 0 ou plus
+ 1 ou plus
? 0 ou 1
{n} exactement n fois
{n,m} de n à m fois
[abc] a, b ou c
[^abc] tout sauf a, b, c
(...) groupe de capture
| OU logique

20. 🌟 Bonnes pratiques

20.1 PEP 8 : le style officiel

Outils :

pip install black flake8 ruff
black mon_fichier.py
flake8 mon_fichier.py
ruff check .

20.2 Environnements virtuels

Isolent les dépendances par projet.

# Création
python -m venv venv

# Activation
# Windows
venv\Scripts\activate
# macOS/Linux
source venv/bin/activate

# Désactivation
deactivate

Une fois activé, pip install ... n'installe que dans cet environnement.

20.3 Le typage statique (annotations)

Optionnel mais très utile :

def addition(a: int, b: int) -> int:
    return a + b

nom: str = "Alice"
notes: list[float] = [12.5, 14.0, 16.5]

from typing import Optional, Union

def trouver(nom: str) -> Optional[dict]:
    ...

Vérification statique avec mypy :

pip install mypy
mypy mon_fichier.py

20.4 Le module logging plutôt que print

import logging

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s"
)

logging.debug("détail technique")
logging.info("information")
logging.warning("attention")
logging.error("erreur")
logging.critical("critique")

20.5 Tests unitaires avec unittest ou pytest

# test_calc.py
def addition(a, b):
    return a + b

def test_addition():
    assert addition(2, 3) == 5
    assert addition(-1, 1) == 0
pip install pytest
pytest

20.6 Le Zen de Python

import this

Quelques principes :


21. 🎓 Mini‑projets de fin de cours

21.1 Projet 1 — Jeu du « plus ou moins »

import random

def jeu():
    secret = random.randint(1, 100)
    essais = 0
    print("J'ai choisi un nombre entre 1 et 100. À toi !")
    while True:
        try:
            proposition = int(input("> "))
        except ValueError:
            print("Entre un entier valide.")
            continue
        essais += 1
        if proposition < secret:
            print("Plus grand !")
        elif proposition > secret:
            print("Plus petit !")
        else:
            print(f"Bravo ! Trouvé en {essais} essais.")
            break

if __name__ == "__main__":
    jeu()

21.2 Projet 2 — Gestionnaire de tâches en JSON

import json
from pathlib import Path

FICHIER = Path("taches.json")

def charger():
    if not FICHIER.exists():
        return []
    return json.loads(FICHIER.read_text(encoding="utf-8"))

def sauver(taches):
    FICHIER.write_text(
        json.dumps(taches, ensure_ascii=False, indent=2),
        encoding="utf-8"
    )

def ajouter(titre):
    taches = charger()
    taches.append({"titre": titre, "fait": False})
    sauver(taches)

def lister():
    for i, t in enumerate(charger(), start=1):
        statut = "✓" if t["fait"] else " "
        print(f"{i}. [{statut}] {t['titre']}")

def cocher(num):
    taches = charger()
    taches[num - 1]["fait"] = True
    sauver(taches)

def menu():
    while True:
        print("\n1) Ajouter  2) Lister  3) Cocher  4) Quitter")
        choix = input("> ").strip()
        if choix == "1":
            ajouter(input("Titre : "))
        elif choix == "2":
            lister()
        elif choix == "3":
            cocher(int(input("Numéro : ")))
        elif choix == "4":
            break

if __name__ == "__main__":
    menu()

21.3 Projet 3 — Compteur de mots dans un fichier

import sys
import re
from collections import Counter

def compter(chemin, top=10):
    with open(chemin, encoding="utf-8") as f:
        texte = f.read().lower()
    mots = re.findall(r"[a-zàâäéèêëïîôöùûüç]+", texte)
    compteur = Counter(mots)
    for mot, n in compteur.most_common(top):
        print(f"{mot:20} {n}")

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage: python compter.py <fichier>")
        sys.exit(1)
    compter(sys.argv[1])

21.4 Projet 4 — Renommer en masse des fichiers

from pathlib import Path
import argparse

def renommer(dossier, prefixe):
    p = Path(dossier)
    for i, fichier in enumerate(sorted(p.iterdir()), start=1):
        if fichier.is_file():
            nouveau = p / f"{prefixe}_{i:03d}{fichier.suffix}"
            print(f"{fichier.name}  →  {nouveau.name}")
            fichier.rename(nouveau)

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("dossier")
    parser.add_argument("prefixe")
    args = parser.parse_args()
    renommer(args.dossier, args.prefixe)

21.5 Projet 5 — Mini gestionnaire de contacts (POO)

from dataclasses import dataclass, asdict
import json
from pathlib import Path

@dataclass
class Contact:
    nom: str
    tel: str
    email: str = ""

class Carnet:
    def __init__(self, fichier="carnet.json"):
        self.fichier = Path(fichier)
        self.contacts: list[Contact] = []
        self.charger()

    def charger(self):
        if self.fichier.exists():
            data = json.loads(self.fichier.read_text(encoding="utf-8"))
            self.contacts = [Contact(**c) for c in data]

    def sauver(self):
        data = [asdict(c) for c in self.contacts]
        self.fichier.write_text(
            json.dumps(data, ensure_ascii=False, indent=2),
            encoding="utf-8"
        )

    def ajouter(self, contact: Contact):
        self.contacts.append(contact)
        self.sauver()

    def chercher(self, motif: str) -> list[Contact]:
        motif = motif.lower()
        return [c for c in self.contacts if motif in c.nom.lower()]

    def __repr__(self):
        return "\n".join(f"- {c.nom} : {c.tel}" for c in self.contacts)


if __name__ == "__main__":
    carnet = Carnet()
    carnet.ajouter(Contact("Alice", "0102030405", "alice@ex.fr"))
    carnet.ajouter(Contact("Bob", "0607080910"))
    print(carnet)
    print("---")
    print(carnet.chercher("ali"))

🏁 Conclusion

Tu disposes maintenant de toutes les bases pour scripter en Python :

✅ Syntaxe et types de base
✅ Structures de contrôle, fonctions
✅ Collections (list, tuple, dict, set)
✅ Modules, fichiers, exceptions
✅ POO, itérateurs, générateurs, décorateurs
✅ Scripting (argparse, sys, subprocess)
✅ Bonnes pratiques (PEP 8, venv, typage)

Prochaines étapes recommandées

  1. Pratique, pratique, pratique. Refais chaque exemple sans regarder.
  2. Choisis un projet personnel (scraper un site, automatiser une tâche
    répétitive, créer un bot Discord, etc.).
  3. Explore une bibliothèque selon tes intérêts :
    • Web : requests, Flask, FastAPI
    • Data : pandas, numpy, matplotlib
    • Automation : selenium, pyautogui, schedule
    • GUI : tkinter, PyQt, customtkinter
  4. Lis du code existant sur GitHub : c'est le meilleur moyen de progresser.
  5. Apprends Git pour versionner tes scripts.

Bonne route avec Python ! 🐍✨

Attached Files

Loading attached files...

Comments

No comments yet. Be the first to comment!

Search Results