Le concept de portée (scope) définit la manière dont les variables et les noms sont recherchés dans votre code.
Elle détermine la visibilité d'une variable dans le programme.
La portée d’un nom ou d’une variable dépend de l’endroit où cette variable est créée dans le code.
En Python, la gestion de la portée repose sur une règle appelée LEGB.
La Règle LEGB
L'acronyme LEGB signifie :
- Local : La portée locale d’une fonction ou d’une expression lambda.
Elle contient les noms définis à l’intérieur de la fonction et n'est accessible que dans cette fonction.
- Enclosing : La portée d’une fonction englobante dans le cas de fonctions imbriquées.
Cette portée permet aux fonctions imbriquées d’accéder aux variables définies dans leur fonction parente.
- Global : La portée au niveau du module. Les noms définis dans un module sont accessibles partout dans le code du module.
- Built-in : La portée des noms intégrés de Python, contenant les mots-clés, fonctions et exceptions prédéfinis du langage.
Lorsqu’un nom est référencé dans un programme, Python suit l'ordre LEGB signifie :pour le rechercher et le résoudre.
Comprendre la Portée en Python
En programmation, la portée d’un nom définit la zone d’un programme où ce nom peut être utilisé sans ambiguïté.
On distingue généralement deux grandes portées:
- Portée globale : Les noms définis ici sont accessibles dans tout le programme.
- Portée locale : Les noms définis ici sont accessibles uniquement dans un bloc de code spécifique, comme à l'intérieur d'une fonction.
Pourquoi la notion de portée est-elle apparue ?
Dans les premiers langages de programmation (comme BASIC ) , toutes les variables étaient globales, ce qui posait de nombreux problèmes de maintenance et de débogage.
Toute partie du programme pouvait modifier n'importe quelle variable à tout moment, ce qui rendait le suivi des valeurs très difficile.
Python, comme d’autres langages modernes, utilise la notion de LEGB pour éviter ces problèmes en limitant la visibilité des variables .
La Différence Entre Portée et Espace de Noms
En Python, la notion de portée est liée à celle d’espace de noms (namespace).
Un espace de noms est un dictionnaire qui associe des noms à des objets
Par exemple, l’espace de noms d’un module est stocké dans module.__dict__ . Vous pouvez explorer les noms définis dans un module avec :
python
import sys
print(sys.__dict__.keys()) # Affiche tous les noms du module sys
Utilisation de la Règle LEGB en Python
Lorsqu’un nom est utilisé, Python suit l’ordre LEGB pour rechercher ce nom :
- Portée locale (L) : Python vérifie d’abord si le nom est défini dans la fonction ou la structure actuelle.
- Portée englobante (E) : Si le nom n'est pas trouvé, Python cherche dans la fonction englobante (si applicable).
- Portée globale (G) : Ensuite, Python cherche dans le module global.
- Portée intégrée (B) : Enfin, Python recherche dans la portée des fonctions et mots-clés intégrés (builtins).
Si le nom n'existe pas dans ces portées, une erreur est levée (NameError).
Exemple d’application de LEGB
x = 10 # Portée globale
def outer():
x = 20 # Portée englobante
def inner():
x = 30 # Portée locale
print(x) # Résout à 30
inner()
print(x) # Résout à 20
outer()
print(x) # Résout à 10
Modifier la Portée en Python
Python fournit deux mots-clés pour modifier le comportement standard de la portée :
1. Le mot-clé global
- Permet de modifier une variable globale à l’intérieur d’une fonction.
counter = 0 # Variable globale
def increment():
global counter # Déclare counter comme globale
counter += 1
increment()
print(counter) # Affiche 1
2. Le mot-clé nonlocal
- Permet de modifier une variable définie dans une portée englobante (non locale).
def outer():
x = 10 # Variable englobante
def inner():
nonlocal x # Modifie x de la fonction outer
x += 5
inner()
print(x) # Affiche 15
outer()
Autres Concepts Liés à la Portée
1. La Portée dans les Fonctions Imbriquées
Les fonctions imbriquées peuvent accéder aux variables de leur fonction englobante, mais elles ne peuvent pas les modifier sans nonlocal.
def outer():
message = "Hello"
def inner():
print(message) # Fonctionne (lecture)
inner()
2. Portée Globale dans les Modules
Chaque module Python a sa propre portée globale , ce qui signifie que les variables globales définies dans un module ne sont pas visibles dans d'autres modules, sauf si elles sont importées .
# module1.py
x = 42
# module2.py
import module1
print(module1.x) # Accès à x défini dans module1
3. Portée dans les Classes
Les classes ont une portée locale, mais leurs attributs sont accessibles via l’instance ou la classe elle-même.
class MyClass:
attr = 100 # Portée de la classe
def __init__(self):
self.instance_attr = 200 # Portée de l'instance
print(MyClass.attr) # 100
obj = MyClass()
print(obj.instance_attr) # 200
4. Portée des Variables de Boucle
En Python, les variables définies dans une compréhension de liste sont locales à cette compréhension :
[item for item in range(5)]
print(item) # Erreur : item n'existe pas hors de la compréhension
Fonctions Utiles pour Travailler avec les Portées
Python fournit des fonctions intégrées pour manipuler et explorer les portées :
- globals() : Renvoie le dictionnaire des variables globales .
- locals() : Renvoie le dictionnaire des variables locales .
- dir(obj) : Liste les attributs et méthodes d’un objet.
- vars(obj) : Renvoie obj.__dict__(utile pour les classes et modules).
print(globals()) # Affiche les variables globales
print(locals()) # Affiche les variables locales
Exemple LEGB avec une fonction Built-in
# Portée globale (G)
sum = "Je suis une chaîne de caractères"
def fonction_externe():
# Portée englobante (E)
sum = [10, 20, 30]
def fonction_interne():
# Portée locale (L)
sum = 100
print("Portée locale :", sum)
fonction_interne()
print("Portée englobante :", sum)
fonction_externe()
print("Portée globale :", sum)
# Récupérer la fonction sum() originale
import builtins
print("Somme correcte :", builtins.sum([1, 2, 3]))
Explication
- Portée locale (L): La variable sum dans fonction_interne() masque les autres sum .
- Portée englobante (E): sum dans fonction_externe() est utilisée si elle n’est pas redéfinie localement.
- Portée globale (G): sum est une chaîne de caractères au niveau global.
- Portée intégrée (B):: La fonction sum() intégrée ne fonctionne plus car sum a été redéfini. On la récupère avec builtins.sum() .
Conclusion
La portée des variables en Python est essentielle pour éviter les erreurs, réduire les bugs et mieux structurer son code.
La règle LEGB vous permet de comprendre comment Python recherche et résout les noms.
- ✅ Éviter les conflits de noms
- ✅ Améliorer la maintenabilité du code
- ✅ Utiliser correctement les variables locales et globales
🔥 Bonne pratique : Évitez les variables globales autant que possible et préférez les variables locales.