Tout savoir sur nonlocal en Python
En Python, le mot-clé nonlocal
est souvent mal compris !
Et pour cause : il n’est utile que dans des cas bien spécifiques, notamment dans des fonctions imbriquées (closures).
Pourtant, bien utilisé, nonlocal
permet de rendre votre code plus propre et plus explicite.
Syntaxe de nonlocal et exemple
Prenons un cas concret : nous avons une fonction à l’intérieur d’une autre, et nous voulons modifier une variable définie dans la fonction parent. Sans nonlocal
, Python créera une nouvelle variable locale au lieu de réutiliser celle de la fonction parente.
nonlocal
permet donc de réutiliser une variable non locale mais pas globale.
Syntaxe
Le mot-clé nonlocale
s'utilise dont au sein d'une fonction imbriquée :
def outer():
var = 10
def inner():
nonlocal var
var += 5
return var
return inner()
Ce qu'il faut retenir de cet exemple :
nonlocal
doit être déclaré avant d'utiliser la variable parente ;- il n'y a pas de nouvelle variable qui est créée : le mot-clé nonlocal vient modifier une variable existante (on parle de portée englobante - nous en reparlerons juste après !).
Enfin ce mot-clé est inutilisable en-dehors d'une fonction contrairement au mot-clé global
.
Exemple
Prenons un exemple plus parlant avec un compteur :
def exterieur():
compteur = 0
def interieur():
nonlocal compteur
compteur += 1
return compteur
return interieur()
Ici, compteur
est dans la portée de exterieur()
, mais pas dans celle de interieur()
. Grâce à nonlocal
, on peut y accéder et la modifier.
Comparaison entre nonlocal et global
Trop souvent quand on débute avec Python nous avons tendance à comparer à tord nonlocal
et global
.
Après tout, une variable qui n'est pas locale est forcément globale ? Non !? 😋
Eh bien non ! Ces deux mots-clé sont totalement différents dans leur fonctionnement.
Faisons une comparaison dans ce tableau récapitulatif :
Mot-clé | Cible | Exemple |
| Variable définie dans le module (à la base) |
Modifier une configuration, faire un paramètre... |
| Variable dans une fonction imbriquée | Closures, compteurs, etc |
Comme nous pouvons le voir, global
vient créer / utiliser une variable disponible dans tout le module, quand nonlocale
vient utiliser une variable dans une fonction parente.
Comprendre la portée fermée (enclosing scope)
En Python, chaque variable vit dans une portée (scope 🇺🇸). Comprendre la portée fermée est essentiel pour utiliser correctement nonlocal
.
Partons de la base !
Il existe 4 niveaux de portée en Python :
- Local : à l'intérieur d'une fonction (ou d'une boucle) ;
- Enclosing : dans une fonction englobante ;
- Global : dans le module courant ;
- Built-in : qui est intégrée par Python.
Avec nonlocal
nous agissons uniquement sur la portée englobante (donc sur ce qu'on appelle enclosing).
Les erreurs courantes avec nonlocal
Faisons un tour des erreurs les plus courantes quand on débute avec nonlocale
! 😬
Erreur #1 : Utiliser nonlocale définir une variable dans la portée fermée
C'est l'erreur la plus courante : on oubli de déclarer notre variable dans notre fonction parente.
def test():
def inner():
nonlocal x # Erreur !
x = 1
inner()
Une variable doit déjà exister dans la fonction englobante. Sinon, nonlocal
échouera (car Python ne trouvera pas notre variable).
Erreur #2 : Créer un conflit avec une variable globale
Voilà une seconde erreur très présente quand on débute avec le mot-clé nonlocal
!
x = 0
def outer():
def inner():
nonlocal x # Erreur : x est global, pas dans une fonction englobante
x += 1
Ici, x
est global, donc nonlocal
ne peut pas l’atteindre.
Erreur #3 : Déclarer nonlocal trop tôt
C'est une autre erreur qu'on retrouve trop souvent : il faut toujours déclarer nonlocal
avant d'utiliser une variable parente.
def outer():
val = 10
def inner():
val = 20 # masque la variable de la fonction englobante
nonlocal val # ❌ Erreur : ordre incorrect
val += 1
Limitations de nonlocal
ien que pratique, nonlocal
possède des restrictions strictes à connaître.
Limitation #1 : Il nécessite une fonction imbriquée
Nous l'avons déjà vu ensemble, il faut impérativement être dans une fonction imbriquée.
# Ceci ne fonctionne pas
nonlocal x # ❌ SyntaxError
Le mot-clé
nonlocal
ne s’applique pas aux variables globales. Pour cela, il faut utiliserglobal
.
Limitation #2 : Pas de déclaration multiple
Contrairement à global
, on ne peut pas combiner plusieurs noms avec une seule déclaration.
Ceci n'est donc pas possible :
# ❌ Erreur
nonlocal x, y # interdit
Chaque variable doit être déclarée une par une.
Questions fréquentes sur le mot-clé nonlocal
Voici les questions les plus fréquentes quand on débute avec le mot-clé nonlocal
. 🥸
Peut-on combiner
nonlocal
etglobal
?
Non. Une variable ne peut pas être à la fois global
et nonlocal
. Cela générerait une erreur de portée.
Peut-on l’utiliser dans une classe ?
Pas directement. Les classes ont leur propre modèle de portée. Utilisez plutôt les attributs d’instance (avec self.var
donc) ou des closures imbriquées dans des méthodes si nécessaire.
Est-ce que
nonlocal
ralentit l’exécution du code ?
Non ! Son impact est quasi nul en termes de performance.
Comment apprendre correctement Python ?
Vous pouvez suivre une formation complètement à jour sur les dernières nouveautés de Python en cliquant ici.