Believemy logo purple

Tout savoir sur nonlocal en Python

Le mot-clé nonlocal est utilisé dans les fonctions imbriquées pour modifier une variable définie dans la fonction parent.
Believemy logo

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 :

PYTHON
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 :

PYTHON
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éCibleExemple

global

Variable définie dans le module (à la base)

Modifier une configuration, faire un paramètre...

nonlocale

Variable dans une fonction imbriquéeClosures, 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 :

  1. Local : à l'intérieur d'une fonction (ou d'une boucle) ;
  2. Enclosing : dans une fonction englobante ;
  3. Global : dans le module courant ;
  4. 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.

PYTHON
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 !

PYTHON
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.

PYTHON
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.

PYTHON
# Ceci ne fonctionne pas
nonlocal x  # ❌ SyntaxError

Le mot-clé nonlocal ne s’applique pas aux variables globales. Pour cela, il faut utiliser global.

 

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 :

PYTHON
# ❌ 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 et global ?

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.

Découvrez notre glossaire Python

Parcourez les termes et définitions les plus couramment utilisés dans le domaine du développement avec Python.