
Comprendre la règle LEGB (Local, Enclosing, Global, Built-in)
Maîtrisez la règle LEGB en Python (Local, Enclosing, Global, Built-in). Découvrez comment Python recherche les noms de variables et comprenez la portée des variables dans différents contextes.
Qu'est-ce que la règle LEGB ? Un ordre de recherche des noms
La règle LEGB est un acronyme qui décrit l'ordre dans lequel Python recherche les noms de variables (ou plus généralement, les noms) lorsqu'il les rencontre dans le code.
LEGB signifie :
- Local : La portée locale (à l'intérieur de la fonction courante).
- Enclosing : Les portées englobantes (les fonctions qui englobent la fonction courante, le cas échéant).
- Global : La portée globale (au niveau du module).
- Built-in : La portée intégrée (les noms prédéfinis dans Python, comme `print`, `len`, `int`, etc.).
Lorsque Python rencontre un nom (par exemple, une variable, une fonction, une classe), il le recherche dans cet ordre : d'abord dans la portée locale, puis dans les portées englobantes (s'il y en a), puis dans la portée globale, et enfin dans la portée intégrée. Dès qu'il trouve le nom, la recherche s'arrête.
Comprendre la règle LEGB est essentiel pour comprendre comment Python gère les variables et pour éviter les erreurs liées à la portée des variables.
L : Local - La portée de la fonction courante
La portée locale est la portée de la fonction dans laquelle le code est en cours d'exécution. Elle inclut :
- Les variables locales définies à l'intérieur de la fonction.
- Les paramètres de la fonction.
Exemple :
def ma_fonction(a):
b = 10 # b est une variable locale
print(a + b) # a et b sont accessibles ici (portée locale)
ma_fonction(5)Dans cet exemple, `a` (le paramètre) et `b` (la variable locale) sont dans la portée locale de `ma_fonction`. Ils ne sont accessibles qu'à l'intérieur de cette fonction.
E : Enclosing - Les portées des fonctions englobantes
La portée englobante (ou "enclosing scope") fait référence aux portées des fonctions qui englobent la fonction courante, dans le cas de fonctions imbriquées (fonctions définies à l'intérieur d'autres fonctions).
Exemple :
def fonction_externe():
x = 10 # x est dans la portée englobante de fonction_interne
def fonction_interne():
print(x) # x est accessible ici (portée englobante)
fonction_interne()Dans cet exemple, `x` est une variable locale à `fonction_externe`. `fonction_interne` est définie à l'intérieur de `fonction_externe`. `fonction_interne` peut accéder à `x` car `x` est dans sa portée englobante.
Si une variable n'est pas trouvée dans la portée locale, Python la recherche dans les portées englobantes, de la plus proche à la plus éloignée.
C'est dans ce contexte qu'intervient le mot-clé `nonlocal` (vu précédemment).
G : Global - La portée du module
La portée globale est la portée du module (le fichier Python) dans lequel le code est en cours d'exécution. Elle inclut les variables globales définies au niveau du module.
Exemple :
y = 20 # y est une variable globale
def ma_fonction():
print(y) # y est accessible ici (portée globale)
ma_fonction()Dans cet exemple, `y` est une variable globale. Elle est accessible depuis n'importe quelle partie du module, y compris à l'intérieur de `ma_fonction`.
Si une variable n'est pas trouvée dans la portée locale ni dans les portées englobantes, Python la recherche dans la portée globale.
C'est dans ce contexte qu'intervient le mot clé `global` (vu précédemment).
B : Built-in - La portée intégrée
La portée intégrée (ou "built-in scope") contient les noms prédéfinis dans Python, comme les fonctions intégrées (`print`, `len`, `int`, `str`, `list`, etc.), les exceptions (`ValueError`, `TypeError`, etc.), et les constantes (`True`, `False`, `None`).
Ces noms sont toujours accessibles, depuis n'importe quelle partie du code.
Exemple :
print(len([1, 2, 3])) # print et len sont des noms intégrés (built-in)Si une variable n'est pas trouvée dans la portée locale, ni dans les portées englobantes, ni dans la portée globale, Python la recherche dans la portée intégrée. Si elle n'est pas trouvée, une erreur `NameError` est levée.
Exemple complet illustrant la règle LEGB
Voici un exemple complet qui illustre la règle LEGB :
x = "global"
def outer():
x = "enclosing"
def inner():
x = "local"
print(x) # L : Recherche d'abord dans la portée locale -> affiche "local"
inner()
print(x) # E : Recherche dans la portée englobante -> affiche "enclosing"
outer()
print(x) # G : Recherche dans la portée globale -> affiche "global"
print(len([1,2])) # B : Recherche dans la portée Built-in -> 2Dans cet exemple :
- La première instruction `print(x)` dans `inner()` affiche "local", car `x` est trouvé dans la portée locale de `inner()`.
- La deuxième instruction `print(x)` dans `outer()` affiche "enclosing", car `x` est trouvé dans la portée englobante de `inner()` (qui est la portée locale de `outer()`).
- La troisième instruction `print(x)` en dehors de toute fonction affiche "global", car `x` est trouvé dans la portée globale.
- L'instruction `print(len([1,2]))` utilise `len` qui est trouvé dans la portée built-in.