Learn in 10 minutes

Learn in 10 minutes

Apprendre Python en 10 minutes

Python est un langage de programmation de haut niveau et interprété, connu pour sa syntaxe concise et ses fonctionnalités puissantes. Ce tutoriel est basé sur la dernière version de Python 3.13+, vous aidant à apprendre rapidement Python.

1. Écrire votre premier programme Python

Commençons par un programme simple. Créez un fichier nommé hello.py et entrez le code suivant :

print("Bonjour, le monde !")

Enregistrez le fichier et exécutez la commande suivante dans le terminal ou la ligne de commande :

python hello.py

La sortie sera :

Bonjour, le monde !

Ce programme simple démontre la fonctionnalité de sortie de base de Python. La fonction print() est utilisée pour afficher des informations textuelles dans la console.

2. Syntaxe de base

La syntaxe de Python est simple et facile à comprendre. Python utilise l’indentation pour définir les blocs de code, contrairement à d’autres langages qui utilisent des accolades {}.

# Ceci est un commentaire
print("Bonjour, le monde !")

Règles de syntaxe de base dans Python :

  • Indentation : Par défaut, 4 espaces sont utilisés pour indiquer le niveau d’un bloc de code. Par exemple, le code à l’intérieur des fonctions ou des boucles doit être indenté.
  • Commentaires : Les commentaires sur une seule ligne commencent par #, tandis que les commentaires sur plusieurs lignes utilisent des triples guillemets """ ou '''.
  • Instructions : Généralement une instruction par ligne, aucun point-virgule ; n’est requis à la fin.
  • Blocs de code : Définis par l’indentation, comme pour les structures if, for, ou les corps de fonctions.

Exemple avec des commentaires multi-lignes :

"""
Ceci est un commentaire multi-lignes,
s'étendant sur plusieurs lignes.
"""

L’indentation est une caractéristique clé de la syntaxe de Python, utilisée pour définir la structure hiérarchique des blocs de code :

if True:
    print("Cette ligne est indentée")
    print("Cette ligne est également indentée")
print("Cette ligne n'est pas indentée")

3. Variables et types de données

En Python, les variables sont des conteneurs pour stocker des données. Python est un langage à typage dynamique, ce qui signifie que vous n’avez pas besoin de déclarer le type d’une variable à l’avance.

Règles de base pour nommer les variables :

  • Les noms de variables ne peuvent contenir que des lettres, des chiffres et des tirets bas.
  • Les noms de variables ne peuvent pas commencer par un chiffre.
  • Les noms de variables sont sensibles à la casse.
  • Les mots-clés de Python ne peuvent pas être utilisés comme noms de variables.

Les types de variables sont déterminés par la valeur assignée. Les principaux types de données de base de Python sont :

  • Entier (int) : par exemple, 42 ou -10, sans limite de taille.
  • Flottant (float) : par exemple, 3.14 ou 2.5e3 (notation scientifique).
  • Chaîne de caractères (str) : par exemple, "bonjour" ou 'monde', en utilisant des guillemets simples ou doubles.
  • Booléen (bool) : True ou False.
  • Type None (NoneType) : Représenté par None, indiquant une valeur nulle ou absente.

Python prend en charge les annotations de type pour améliorer la lisibilité du code, utilisées pour la vérification statique et le support des IDE, sans affecter le comportement à l’exécution :

name: str = "Alice"
age: int = 25

3.1 Types numériques (Number)

Python prend en charge trois types numériques : entier (int), flottant (float) et complexe (complex).

# Entier
age = 25
population = 1000000

# Flottant
temperature = 36.5
pi = 3.14159

# Complexe
complex_num = 3 + 4j

3.2 Chaîne de caractères (String)

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

single_quote = 'Chaîne avec guillemets simples'
double_quote = "Chaîne avec guillemets doubles"
multiline = """Ceci est une
chaîne multi-lignes"""

Opérations sur les chaînes :

text = "Programmation Python"
print(len(text))        # Longueur de la chaîne
print(text.upper())     # Conversion en majuscules
print(text.lower())     # Conversion en minuscules
print(text[0])          # Accès au premier caractère
print(text[2:6])        # Découpage de la chaîne

3.3 Type booléen (Boolean)

Le type booléen a deux valeurs : True et False.

is_active = True
is_complete = False

# Opérations booléennes
result1 = True and False  # False
result2 = True or False   # True
result3 = not True        # False

3.4 Type None (None)

None représente un état nul ou sans valeur.

value = None

if value is None:
    print("La valeur est nulle")

4. Structures de données

Python fournit plusieurs structures de données intégrées pour stocker et manipuler des données. Voici les structures de données couramment utilisées et leur utilisation.

4.1 Liste (List)

Une liste est une collection ordonnée et mutable. Vous pouvez ajouter, supprimer ou modifier des éléments dans une liste. Les listes sont définies avec des crochets [].

numbers = [1, 2, 3, 4, 5]
numbers.append(6)      # Ajouter un élément
numbers.insert(0, 0)   # Insérer à une position spécifique
numbers.remove(3)      # Supprimer une valeur spécifique
numbers[0] = 10        # Modifier un élément
print(numbers)         # [10, 2, 4, 5, 6]

Découpage de liste pour accéder à des sous-listes :

numbers = [10, 20, 30, 40, 50]
print(numbers[1:4])    # Sortie : [20, 30, 40]
print(numbers[:3])     # Sortie : [10, 20, 30]
print(numbers[-2:])    # Sortie : [40, 50]

Compréhension de liste :

squares = [x**2 for x in range(5)]
print(squares)         # [0, 1, 4, 9, 16]

even_squares = [x**2 for x in range(10) if x % 2 == 0]
print(even_squares)    # [0, 4, 16, 36, 64]

4.2 Tuple (Tuple)

Un tuple est une collection ordonnée mais immuable. Une fois créé, ses éléments ne peuvent pas être modifiés. Les tuples sont définis avec des parenthèses (). En raison de leur immutabilité, les tuples sont généralement plus rapides que les listes et peuvent être utilisés comme clés de dictionnaire.

point = (10, 20)
x, y = point  # Dépaquetage
print(x, y)   # Sortie : 10 20

Les tuples à un seul élément nécessitent une virgule :

single_tuple = (42,)

4.3 Dictionnaire (Dict)

Un dictionnaire est une collection non ordonnée (ordonnée à partir de Python 3.7+) de paires clé-valeur. Chaque clé est unique et associée à une valeur. Les dictionnaires sont définis avec des accolades {}.

student = {
    "name": "John",
    "age": 20,
    "major": "Informatique"
}

# Accès et modification du dictionnaire
print(student["name"])
student["age"] = 21
student["gpa"] = 3.8

# Accès sécurisé
print(student.get("phone", "Non fourni"))

# Itération sur le dictionnaire
for key, value in student.items():
    print(f"{key}: {value}")

Compréhension de dictionnaire :

# Créer un dictionnaire de carrés
squares_dict = {x: x**2 for x in range(5)}
print(squares_dict)  # {0: 0, 1: 1, 2: 4, 3: 9, 4: 16}

# Compréhension conditionnelle de dictionnaire
even_squares_dict = {x: x**2 for x in range(10) if x % 2 == 0}
print(even_squares_dict)  # {0: 0, 2: 4, 4: 16, 6: 36, 8: 64}

4.4 Ensemble (Set)

Un ensemble est une collection non ordonnée sans éléments en double. Définis avec des accolades {} ou set().

# Création d'un ensemble
fruits = {"pomme", "banane", "orange"}
numbers = set([1, 2, 3, 3, 4, 4, 5])  # Déduplication automatique
print(numbers)  # {1, 2, 3, 4, 5}

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

print(set1 | set2)  # Union : {1, 2, 3, 4, 5, 6}
print(set1 & set2)  # Intersection : {3, 4}
print(set1 - set2)  # Différence : {1, 2}
print(set1 ^ set2)  # Différence symétrique : {1, 2, 5, 6}

5. Opérations et opérateurs

Python fournit un ensemble riche d’opérateurs pour divers calculs et comparaisons, incluant les opérateurs arithmétiques, de comparaison, logiques, binaires et d’identité.

  • Opérateurs arithmétiques : +, -, *, /, // (division entière), % (modulo), ** (exponentiation).
  • Opérateurs de comparaison : ==, !=, >, <, >=, <=.
  • Opérateurs logiques : and, or, not.
  • Opérateurs d’appartenance : in, not in.
  • Opérateurs d’identité : is, is not.

5.1 Opérateurs arithmétiques

Les opérateurs arithmétiques sont utilisés pour des opérations mathématiques. La priorité des opérateurs suit les règles mathématiques (par exemple, ** a une priorité plus élevée que + ou -). Les parenthèses () peuvent être utilisées pour modifier la priorité.

a, b = 10, 3

print(f"Addition : {a + b}")      # 13
print(f"Soustraction : {a - b}")   # 7
print(f"Multiplication : {a * b}")  # 30
print(f"Division : {a / b}")      # 3.333...
print(f"Division entière : {a // b}")  # 3
print(f"Modulo : {a % b}")      # 1
print(f"Exponentiation : {a ** b}")  # 1000

5.2 Opérateurs de comparaison

Les opérateurs de comparaison comparent deux valeurs et renvoient un booléen (True ou False).

x, y = 5, 10

print(f"Égal : {x == y}")     # False
print(f"Différent : {x != y}") # True
print(f"Supérieur à : {x > y}")  # False
print(f"Inférieur à : {x < y}")  # True
print(f"Supérieur ou égal : {x >= y}")  # False
print(f"Inférieur ou égal : {x <= y}")  # True

5.3 Opérateurs logiques

Les opérateurs logiques combinent ou manipulent des valeurs booléennes (True ou False), généralement utilisés dans des instructions conditionnelles.

a, b = True, False

print(f"Opération ET : {a and b}")  # False
print(f"Opération OU : {a or b}")    # True
print(f"Opération NON : {not a}")    # False

5.4 Opérateurs d’identité

L’opérateur is compare l’identité de deux objets, vérifiant s’ils pointent vers la même adresse mémoire (pas seulement des valeurs égales). Il diffère de ==, qui compare le contenu.

list1 = [1, 2, 3]
list2 = [1, 2, 3]
list3 = list1

print(f"list1 is list2 : {list1 is list2}")    # False
print(f"list1 is list3 : {list1 is list3}")    # True
print(f"list1 == list2 : {list1 == list2}")    # True

5.5 Opérateurs d’appartenance

Les opérateurs d’appartenance testent si une valeur fait partie d’une séquence (par exemple, liste, tuple, chaîne, ensemble), renvoyant un booléen.

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

print(f"'pomme' in fruits : {'pomme' in fruits}")        # True
print(f"'raisin' not in fruits : {'raisin' not in fruits}")  # True

6. Contrôle de flux

Python fournit plusieurs instructions de contrôle de flux pour gérer l’ordre d’exécution d’un programme.

6.1 Instructions if

L’instruction if évalue une condition et exécute son bloc si la condition est True. Utilisez elif et else pour des conditions complexes.

age = 20
if age >= 18:
    print("Adulte")
elif age >= 13:
    print("Adolescent")
else:
    print("Enfant")

6.2 Boucles for

La boucle for itère sur un objet itérable (par exemple, liste, tuple, chaîne, ou range).

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

# Utilisation de range() pour boucler
for i in range(5):
    print(i)  # Sortie : 0, 1, 2, 3, 4

6.3 Boucles while

La boucle while continue d’exécuter un bloc tant que sa condition reste True.

count = 0
while count < 5:
    print(count)
    count += 1
  • break et continue : break sort de la boucle, continue saute l’itération actuelle.
for i in range(10):
    if i == 5:
        break
    if i % 2 == 0:
        continue
    print(i)  # Sortie : 1, 3

6.4 Instructions match

Introduites dans Python 3.10, les instructions match offrent un puissant appariement de motifs structurels, servant d’alternative avancée aux chaînes if/elif/else.

http_status = 200

match http_status:
    case 200 | 201:
        print("Succès")
    case 404:
        print("Non trouvé")
    case 500:
        print("Erreur serveur")
    case _:  # Caractère générique, correspond à tout autre cas
        print("Statut inconnu")

7. Entrée et sortie

7.1 Entrée et sortie de base

Utilisez la fonction input() pour obtenir une entrée utilisateur et la fonction print() pour afficher des informations.

# Obtenir une entrée utilisateur
name = input("Veuillez entrer votre nom : ")
age = int(input("Veuillez entrer votre âge : "))

# Afficher des informations
print("Bienvenue", name)
print("Vous avez", age, "ans")

7.2 Sortie formatée (f-strings)

Introduites dans Python 3.6+, les f-strings (littéraux de chaînes formatées) sont un moyen pratique et puissant de formater les chaînes. Préfixez une chaîne avec f ou F et intégrez des variables ou des expressions dans des accolades {}.

user = "Alice"
items = 3
total_cost = 45.5

# Utilisation de f-string pour un message formaté
message = f"L'utilisateur {user} a acheté {items} articles pour {total_cost:.2f} $."
print(message)

# Expressions dans les f-strings
print(f"2 + 3 égale {2 + 3}")

Expressions et appels de fonctions dans les f-strings :

width = 10
height = 5

# Utilisation d'expressions dans les f-strings
area = f"Aire du rectangle : {width * height}"
print(area)

# Appeler des fonctions
text = "python"
formatted = f"Majuscules : {text.upper()}, Longueur : {len(text)}"
print(formatted)

Options de formatage dans les f-strings :

pi = 3.14159265359
large_number = 1234567

# Formatage des nombres
print(f"Pi (2 décimales) : {pi:.2f}")
print(f"Pi (4 décimales) : {pi:.4f}")
print(f"Grand nombre (milliers) : {large_number:,}")
print(f"Pourcentage : {0.85:.1%}")

# Alignement des chaînes
name = "Python"
print(f"Alignement à gauche : '{name:<10}'")
print(f"Alignement à droite : '{name:>10}'")
print(f"Alignement au centre : '{name:^10}'")

Formatage de la date et de l’heure avec les f-strings :

from datetime import datetime

now = datetime.now()
print(f"Heure actuelle : {now}")
print(f"Heure formatée : {now:%Y-%m-%d %H:%M:%S}")
print(f"Date uniquement : {now:%Y-%m-%d}")

9. Fonctions

Les fonctions en Python sont des blocs de code réutilisables pour des tâches spécifiques, définies avec le mot-clé def, prenant en charge les paramètres par défaut, les arguments variables et les arguments par mot-clé.

Définition de fonction de base :

def greet(name):
    """Fonction de salutation"""
    return f"Bonjour, {name} !"

# Appel de la fonction
message = greet("John")
print(message)

Arguments par mot-clé :

Les arguments par mot-clé sont passés en utilisant la syntaxe nom_paramètre=valeur.

def greet(name, greeting="Bonjour"):
    return f"{greeting}, {name} !"

print(greet("Alice"))          # Sortie : Bonjour, Alice !
print(greet("Bob", "Salut"))   # Sortie : Salut, Bob !

Arguments variables :

Les arguments variables permettent aux fonctions d’accepter un nombre arbitraire d’arguments, soit positionnels (*args) soit par mot-clé (**kwargs).

# Arguments positionnels variables (*args)
def sum_numbers(*args):
    return sum(args)

print(sum_numbers(1, 2, 3, 4))  # Sortie : 10

# Arguments par mot-clé variables (**kwargs)
def print_kwargs(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_kwargs(name="Alice", age=25, city="Pékin")

Annotations de fonction :

Les annotations de fonction ajoutent des métadonnées descriptives aux paramètres et aux valeurs de retour des fonctions, améliorant la lisibilité et la documentation.

def calculate_area(length: float, width: float) -> float:
    """Calculer l'aire d'un rectangle"""
    return length * width

def process_user(name: str, age: int, active: bool = True) -> dict:
    """Traiter les informations de l'utilisateur"""
    return {
        "name": name,
        "age": age,
        "active": active
    }

10. Expressions Lambda

Les expressions lambda créent des fonctions anonymes, offrant un moyen concis de définir de petites fonctions.

square = lambda x: x ** 2
print(square(5))  # Sortie : 25

Couramment utilisées avec des fonctions d’ordre supérieur comme map ou filter :

numbers = [1, 2, 3, 4]
squares = list(map(lambda x: x ** 2, numbers))
print(squares)  # Sortie : [1, 4, 9, 16]

11. Classes et objets

Python prend en charge la programmation orientée objet avec le mot-clé class :

class Person:
    """Classe Personne"""
    
    def __init__(self, name, age):
        """Constructeur"""
        self.name = name
        self.age = age
    
    def introduce(self):
        """Méthode de présentation"""
        return f"Je suis {self.name}, j'ai {self.age} ans"
    
    def have_birthday(self):
        """Méthode d'anniversaire"""
        self.age += 1
        return f"{self.name} a eu un anniversaire, maintenant {self.age} ans"

# Création d'objets
person1 = Person("John", 25)
person2 = Person("Jane", 30)

print(person1.introduce())
print(person2.have_birthday())

11.1 Attributs de classe et d’instance

En Python, les attributs de classe et les attributs d’instance sont deux types d’attributs pour stocker des données dans les classes et les objets.

  • Attributs de classe : Définis en dehors des méthodes, appartiennent à la classe elle-même et sont partagés entre toutes les instances.
  • Attributs d’instance : Définis dans les méthodes (généralement __init__), liés à des instances spécifiques via self.
class Student:
    # Attributs de classe
    school = "Université de Stanford"
    student_count = 0
    
    def __init__(self, name, major):
        # Attributs d'instance
        self.name = name
        self.major = major
        Student.student_count += 1
    
    @classmethod
    def get_student_count(cls):
        """Méthode de classe"""
        return cls.student_count
    
    @staticmethod
    def is_valid_age(age):
        """Méthode statique"""
        return 0 < age < 150

# Exemple d'utilisation
student1 = Student("John", "Informatique")
student2 = Student("Jane", "Mathématiques")

print(f"École : {Student.school}")
print(f"Nombre total d'étudiants : {Student.get_student_count()}")
print(f"Âge valide : {Student.is_valid_age(20)}")

11.2 Héritage de classe

L’héritage permet à une classe (sous-classe) d’hériter des attributs et des méthodes d’une autre classe (classe parente), favorisant la réutilisation et l’extension du code.

class Animal:
    def __init__(self, name, species):
        self.name = name
        self.species = species
    
    def make_sound(self):
        return f"{self.name} émet un son"
    
    def info(self):
        return f"{self.name} est un {self.species}"

class Dog(Animal):
    def __init__(self, name, breed):
        super().__init__(name, "Chien")
        self.breed = breed
    
    def make_sound(self):
        return f"{self.name} aboie"
    
    def fetch(self):
        return f"{self.name} rapporte la balle"

class Cat(Animal):
    def __init__(self, name, color):
        super().__init__(name, "Chat")
        self.color = color
    
    def make_sound(self):
        return f"{self.name} miaule"
    
    def climb(self):
        return f"{self.name} grimpe à un arbre"

# Utilisation de l'héritage
dog = Dog("Buddy", "Golden Retriever")
cat = Cat("Mimi", "Orange")

print(dog.info())
print(dog.make_sound())
print(dog.fetch())

print(cat.info())
print(cat.make_sound())
print(cat.climb())

11.3 Méthodes spéciales (Méthodes magiques)

Les méthodes spéciales (ou méthodes magiques) sont des méthodes à double soulignement qui définissent des comportements spécifiques, appelées automatiquement par Python dans certaines situations.

class Rectangle:
    def __init__(self, width, height):
        self.width = width
        self.height = height
    
    def __str__(self):
        """Représentation sous forme de chaîne"""
        return f"Rectangle({self.width}x{self.height})"
    
    def __repr__(self):
        """Représentation officielle sous forme de chaîne"""
        return f"Rectangle(width={self.width}, height={self.height})"
    
    def __eq__(self, other):
        """Comparaison d'égalité"""
        if isinstance(other, Rectangle):
            return self.width == other.width and self.height == other.height
        return False
    
    def __lt__(self, other):
        """Comparaison inférieur (par aire)"""
        if isinstance(other, Rectangle):
            return self.area() < other.area()
        return NotImplemented
    
    def __add__(self, other):
        """Opération d'addition"""
        if isinstance(other, Rectangle):
            return Rectangle(self.width + other.width, self.height + other.height)
        return NotImplemented
    
    def area(self):
        """Calculer l'aire"""
        return self.width * self.height

# Utilisation des méthodes spéciales
rect1 = Rectangle(3, 4)
rect2 = Rectangle(5, 6)
rect3 = Rectangle(3, 4)

print(rect1)           # Rectangle(3x4)
print(repr(rect1))     # Rectangle(width=3, height=4)
print(rect1 == rect3)  # True
print(rect1 < rect2)   # True
print(rect1 + rect2)   # Rectangle(8x10)

12. Gestionnaires de contexte

Les gestionnaires de contexte assurent une acquisition et une libération appropriées des ressources, couramment utilisés avec l’instruction with pour la gestion des ressources, comme les fichiers ou les connexions à une base de données.

12.1 Utilisation des gestionnaires de contexte

Les opérations sur les fichiers sont un cas d’utilisation courant pour les gestionnaires de contexte :

with open("exemple.txt", "r") as file:
    content = file.read()
    print(content)

L’instruction with garantit que le fichier est automatiquement fermé après les opérations.

12.2 Gestionnaires de contexte personnalisés

Créez des gestionnaires de contexte personnalisés en définissant les méthodes __enter__ et __exit__ :

class DatabaseConnection:
    def __init__(self, database_name):
        self.database_name = database_name
        self.connection = None
    
    def __enter__(self):
        """Appelé lors de l'entrée dans le contexte"""
        print(f"Connexion à la base de données : {self.database_name}")
        self.connection = f"Connexion à {self.database_name}"
        return self.connection
    
    def __exit__(self, exc_type, exc_value, traceback):
        """Appelé lors de la sortie du contexte"""
        print(f"Fermeture de la connexion à la base de données : {self.database_name}")
        if exc_type:
            print(f"Une exception s'est produite : {exc_type.__name__}: {exc_value}")
        self.connection = None
        return False  # Ne pas supprimer les exceptions

# Utilisation du gestionnaire de contexte personnalisé
with DatabaseConnection("base_de_donnees_utilisateur") as conn:
    print(f"Utilisation de la connexion : {conn}")
    print("Effectuer des opérations sur la base de données...")

Utilisation du module contextlib pour créer des gestionnaires de contexte :

from contextlib import contextmanager
import time

@contextmanager
def timer(operation_name):
    """Gestionnaire de contexte de minuterie"""
    print(f"Démarrage de {operation_name}")
    start_time = time.time()
    try:
        yield
    finally:
        end_time = time.time()
        print(f"{operation_name} terminé en {end_time - start_time:.2f} secondes")

# Utilisation du gestionnaire de contexte basé sur un décorateur
with timer("traitement des données"):
    # Simuler une opération longue
    time.sleep(1)
    print("Traitement des données...")

13. Gestion des exceptions

La gestion des exceptions garantit la robustesse du programme, en utilisant try, except, else et finally pour gérer les exceptions.

try:
    result = 10 / 0
except ZeroDivisionError:
    print("Impossible de diviser par zéro !")
else:
    print("Division réussie")
finally:
    print("Ceci s'exécute toujours")

Sortie :

Impossible de diviser par zéro !
Ceci s'exécute toujours

14. Opérations sur les fichiers

Python fournit des méthodes simples pour lire et écrire des fichiers, généralement utilisées avec des gestionnaires de contexte.

14.1 Lecture de fichiers

Lecture du contenu d’un fichier texte :

with open("exemple.txt", "r") as file:
    content = file.read()
    print(content)

Lecture ligne par ligne :

with open("exemple.txt", "r") as file:
    for line in file:
        print(line.strip())

14.2 Écriture dans des fichiers

Écriture dans un fichier texte :

with open("sortie.txt", "w") as file:
    file.write("Bonjour, Python !\n")

Ajout de contenu :

with open("sortie.txt", "a") as file:
    file.write("Ajout de nouveau contenu.\n")

15. Modules et paquets

Les modules sont des fichiers contenant du code Python, et les paquets sont des répertoires contenant plusieurs modules. Importez des modules avec import :

import math
print(math.sqrt(16))  # Sortie : 4.0

Exemple de module personnalisé (supposons que le fichier s’appelle monmodule.py) :

# monmodule.py
def say_hello():
    return "Bonjour depuis le module !"

Importation et utilisation :

import monmodule
print(monmodule.say_hello())  # Sortie : Bonjour depuis le module !

16. Portée et espace de noms

16.1 Portée

La portée définit la région où une variable est accessible. Python suit la règle LEGB pour la recherche de variables :

  • L (Local) : À l’intérieur d’une fonction ou d’une méthode de classe.
  • E (Enclosing) : Dans la fonction externe d’une fonction imbriquée (fermeture).
  • G (Global) : Au niveau du module.
  • B (Built-in) : Fonctions et exceptions intégrées comme print() ou len().
x = "x global"

def outer_func():
    x = "x englobant"
    def inner_func():
        x = "x local"
        print(x) # Accède à la portée locale x
    inner_func()
    print(x) # Accède à la portée englobante x

outer_func()
print(x) # Accède à la portée globale x

Utilisation de global ou nonlocal pour modifier les variables de portée :

x = "global"
def modify_global():
    global x
    x = "modifié"
modify_global()
print(x)  # Sortie : modifié

16.2 Espace de noms

Un espace de noms est une correspondance entre des noms et des objets, comme un dictionnaire où les clés sont des noms de variables et les valeurs sont les objets.

Chaque module, fonction et classe a son propre espace de noms, évitant les conflits de noms. Utilisez globals() et locals() pour inspecter les espaces de noms.

a_variable = 10

def some_function():
    b_variable = 20
    # locals() retourne le dictionnaire de l'espace de noms local actuel
    print(f"Locals : {locals()}")

print(f"Globals : {globals().keys()}") # Affiche les clés de l'espace de noms global
some_function()

17. Générateurs

Les générateurs sont des itérateurs spéciaux qui génèrent des valeurs à la demande, plutôt que de créer toutes les valeurs d’un coup, ce qui les rend efficaces en mémoire pour les grands ensembles de données.

Les générateurs utilisent le mot-clé yield pour retourner des valeurs paresseusement :

def fibonacci(n):
    a, b = 0, 1
    for _ in range(n):
        yield a
        a, b = b, a + b

for num in fibonacci(5):
    print(num)  # Sortie : 0, 1, 1, 2, 3

18. Multithreading

Le multithreading permet à un programme d’exécuter plusieurs opérations simultanément, utile pour les tâches liées aux E/S comme les requêtes réseau ou les opérations sur fichiers.

Le module threading de Python fournit des outils pour créer et gérer des threads. En raison du Global Interpreter Lock (GIL), le multithreading n’atteint pas un véritable parallélisme CPU dans un seul processus, mais il améliore considérablement les performances pour les tâches liées aux E/S.

import threading
import time

def worker(thread_name):
    print(f"Thread {thread_name} démarre...")
    time.sleep(2) # Simule une opération longue
    print(f"Thread {thread_name} terminé.")

# Créer des threads
thread1 = threading.Thread(target=worker, args=("A",))
thread2 = threading.Thread(target=worker, args=("B",))

# Démarrer les threads
thread1.start()
thread2.start()

# Attendre que tous les threads se terminent
thread1.join()
thread2.join()

print("Tous les threads sont terminés.")

19. Programmation asynchrone

La programmation asynchrone est idéale pour les scénarios à forte E/S et à haute concurrence, utilisant une boucle d’événements pour gérer les tâches au lieu des threads.

Python prend en charge la programmation asynchrone via la bibliothèque asyncio et la syntaxe async/await.

  • async def : Définit une coroutine.
  • await : Met en pause l’exécution de la coroutine, attendant qu’un objet awaitable se termine.
import asyncio

async def say_hello():
    print("Bonjour")
    await asyncio.sleep(1) # Sommeil non bloquant, simulant une E/S
    print("Monde")

async def main():
    # Créer et attendre une tâche
    await asyncio.create_task(say_hello())

# Exécuter la coroutine principale
asyncio.run(main())

Sortie :

Bonjour
Monde