Que Sont Les Espaces De Noms Python (Et Pourquoi Sont-Ils Nécessaires?)
Les conflits de noms se produisent tout le temps dans la vie réelle. Par exemple, chaque école où je suis allé avait au moins deux élèves dans ma classe qui partageaient le même prénom. Si quelqu’un venait dans la classe et demandait l’élève X, nous demanderions avec enthousiasme: « De quoi parlez-vous? Il y a deux étudiants nommés X. « Après cela, la personne qui s’enquérait nous donnait un nom de famille et nous lui présentions le bon X.
Toute cette confusion et le processus de détermination de la personne exacte dont nous parlons en cherchant d’autres informations en plus d’un prénom pourraient être évités si tout le monde avait un nom unique. Ce n’est pas un problème dans une classe de 30 élèves. Cependant, il deviendra de plus en plus difficile de trouver un nom unique, significatif et facile à retenir pour chaque enfant d’une école, d’une ville, d’une ville, d’un pays ou du monde entier. Un autre problème en fournissant à chaque enfant un nom unique est que le processus de détermination si quelqu’un d’autre a également nommé son enfant Macey, Maci ou Macie pourrait être très fatigant.
Un conflit très similaire peut également survenir dans la programmation. Lorsque vous écrivez un programme de seulement 30 lignes sans dépendances externes, il est très facile de donner des noms uniques et significatifs à toutes vos variables. Le problème se pose lorsqu’il y a des milliers de lignes dans un programme et que vous avez également chargé des modules externes. Dans ce tutoriel, vous découvrirez les espaces de noms, leur importance et la résolution de la portée en Python.
Que Sont Les Espaces De Noms ?
Un espace de noms est essentiellement un système pour s’assurer que tous les noms d’un programme sont uniques et peuvent être utilisés sans conflit. Vous savez peut—être déjà que tout dans les chaînes de type Python, les listes, les fonctions, etc.- est un objet. Un autre fait intéressant est que Python implémente des espaces de noms en tant que dictionnaires. Il existe un mappage nom-objet, avec les noms comme clés et les objets comme valeurs. Plusieurs espaces de noms peuvent utiliser le même nom et le mapper à un objet différent. Voici quelques exemples d’espaces de noms :
- Espace de noms local: Cet espace de noms inclut des noms locaux à l’intérieur d’une fonction. Cet espace de noms est créé lorsqu’une fonction est appelée et ne dure que jusqu’au retour de la fonction.
- Espace de noms global : Cet espace de noms inclut les noms de divers modules importés que vous utilisez dans un projet. Il est créé lorsque le module est inclus dans le projet et dure jusqu’à la fin du script.
- Espace de noms intégré : Cet espace de noms inclut des fonctions intégrées et des noms d’exceptions intégrés.
Dans les Modules mathématiques de la série Python sur Envato Tuts+, j’ai écrit sur les fonctions mathématiques utiles disponibles dans différents modules. Par exemple, les modules math et cmath ont beaucoup de fonctions communes aux deux, comme log10()
acos()
cos()
exp()
, etc. Si vous utilisez ces deux modules dans le même programme, la seule façon d’utiliser ces fonctions sans ambiguïté est de les préfixer avec le nom du module, comme math.log10()
et cmath.log10()
.
Qu’Est-Ce Que Scope ?
Les espaces de noms nous aident à identifier de manière unique tous les noms d’un programme. Cependant, cela n’implique pas que nous puissions utiliser un nom de variable où nous le voulons. Un nom a également une portée qui définit les parties du programme où vous pouvez utiliser ce nom sans utiliser de préfixe. Tout comme les espaces de noms, il existe également plusieurs étendues dans un programme. Voici une liste de quelques étendues qui peuvent exister lors de l’exécution d’un programme.
- Une portée locale, qui est la portée la plus interne qui contient une liste de noms locaux disponibles dans la fonction en cours.
- Une portée de toutes les fonctions englobantes. La recherche d’un nom commence à partir de la portée englobante la plus proche et se déplace vers l’extérieur.
- Une portée de niveau de module qui contient tous les noms globaux du module actuel.
- La portée la plus externe qui contient une liste de tous les noms intégrés. Cette portée est recherchée en dernier pour trouver le nom que vous avez référencé.
Dans les prochaines sections de ce tutoriel, nous utiliserons largement la fonction Python dir() intégrée pour renvoyer une liste de noms dans la portée locale actuelle. Cela vous aidera à comprendre plus clairement le concept d’espaces de noms et la portée.
Résolution de portée
Comme je l’ai mentionné dans la section précédente, la recherche d’un nom donné commence à partir de la fonction la plus interne, puis se déplace de plus en plus haut jusqu’à ce que le programme puisse mapper ce nom à un objet. Lorsqu’aucun nom de ce type n’est trouvé dans l’un des espaces de noms, le programme déclenche une exception NameError.
Avant de commencer, essayez de taper dir()
dans IDLE ou tout autreE Python.
dir()#
Voyons la sortie de la fonction dir()
après avoir défini une variable et une fonction.
a_num = 10dir()# def some_func(): b_num = 11 print(dir()) some_func()# dir()#
La fonction dir()
affiche uniquement la liste des noms dans la portée actuelle. C’est pourquoi dans la portée de some_func()
, il n’y a qu’un seul nom appelé b_num
. Appeler dir()
après avoir défini some_func()
l’ajoute à la liste des noms disponibles dans l’espace de noms global.
Maintenant, voyons la liste des noms dans certaines fonctions imbriquées. Le code de ce bloc continue à partir du bloc précédent.
Le code ci-dessus définit deux variables et une fonction à l’intérieur de la portée de outer_func()
. Dans inner_func()
, la fonction dir()
affiche uniquement le nom d_num
. Cela semble juste car d_num
est la seule variable définie là-dedans.
Sauf indication explicite en utilisant global
, la réaffectation d’un nom global dans un espace de noms local crée une nouvelle variable locale portant le même nom. Ceci est évident à partir du code suivant.
À l’intérieur des outer_func()
et inner_func()
a_num
a été déclaré comme une variable globale. Nous définissons simplement une valeur différente pour la même variable globale. C’est la raison pour laquelle la valeur de a_num
à tous les emplacements est de 20. D’autre part, chaque fonction crée sa propre variable b_num
avec une portée locale, et la fonction print()
imprime la valeur de cette variable à portée locale.
Importer correctement des modules
Il est très courant d’importer des modules externes dans vos projets pour accélérer le développement. Il existe trois façons différentes d’importer des modules. Dans cette section, vous en apprendrez plus sur toutes ces méthodes, en discutant en détail de leurs avantages et de leurs inconvénients.
-
from module import *
: Cette méthode d’importation d’un module importe tous les noms du module donné directement dans votre espace de noms actuel. Vous pourriez être tenté d’utiliser cette méthode car elle vous permet d’utiliser une fonction directement sans ajouter le nom du module comme préfixe. Cependant, il est très sujet aux erreurs et vous perdez également la possibilité de dire quel module a réellement importé cette fonction. Voici un exemple d’utilisation de cette méthode:
Si vous connaissez les modules math et cmath, vous savez déjà qu’il existe quelques noms communs qui sont définis dans ces deux modules mais s’appliquent respectivement aux nombres réels et complexes.
Puisque nous avons importé le module cmath après le module math, il écrase les définitions de fonctions de ces fonctions communes à partir du module math. C’est pourquoi le premier log10(125)
renvoie un nombre réel et le second log10(125)
renvoie un nombre complexe. Il n’y a aucun moyen pour vous d’utiliser la fonction log10()
du module de mathématiques maintenant. Même si vous avez essayé de taper math.log10(125)
, vous obtiendrez une exception NameError car math
n’existe pas réellement dans l’espace de noms.
L’essentiel est que vous ne devriez pas utiliser cette façon d’importer des fonctions de différents modules juste pour enregistrer quelques frappes.
-
from module import nameA, nameB
: Si vous savez que vous n’utiliserez qu’un ou deux noms à partir d’un module, vous pouvez les importer directement en utilisant cette méthode. De cette façon, vous pouvez écrire le code de manière plus concise tout en réduisant au minimum la pollution de l’espace de noms. Cependant, gardez à l’esprit que vous ne pouvez toujours pas utiliser d’autre nom du module en utilisantmodule.nameZ
. Toute fonction portant le même nom dans votre programme écrasera également la définition de cette fonction importée à partir du module. Cela rendra la fonction importée inutilisable. Voici un exemple d’utilisation de cette méthode :
dir()# from math import log2, log10dir()# log10(125)# 2.0969100130080562
-
import module
: C’est le moyen le plus sûr et recommandé d’importer un module. Le seul inconvénient est que vous devrez préfixer le nom du module à tous les noms que vous allez utiliser dans le programme. Cependant, vous pourrez éviter la pollution de l’espace de noms et également définir des fonctions dont les noms correspondent au nom des fonctions du module.
dir()# import mathdir()# math.log10(125)# 2.0969100130080562
Pensées finales
J’espère que ce tutoriel vous a aidé à comprendre les espaces de noms et leur importance. Vous devriez maintenant être en mesure de déterminer la portée des différents noms dans un programme et d’éviter les pièges potentiels.
De plus, n’hésitez pas à voir ce que nous avons à vendre et à étudier sur le marché, et n’hésitez pas à poser des questions et à fournir vos précieux commentaires en utilisant le flux ci-dessous.
La dernière section de l’article a discuté des différentes façons d’importer des modules en Python et des avantages et inconvénients de chacun d’eux. Si vous avez des questions liées à ce sujet, veuillez me le faire savoir dans les commentaires.
Apprenez Python
Apprenez Python avec notre guide didacticiel complet sur Python, que vous commenciez à peine ou que vous soyez un codeur chevronné cherchant à acquérir de nouvelles compétences.