Les conflits de noms se produisent tout le temps dans la vie réelle. Par exemple, chaque école dans laquelle je suis allé a au moins deux élèves de ma classe qui portent le même prénom. Si quelqu'un entrait dans la classe et demandait l'élève X, nous demandions avec enthousiasme: "De qui parlez-vous? Il y a deux élèves nommés X." Après cela, le chercheur nous donnait un nom de famille et nous le présentions au bon X.
Toute cette confusion et le processus de détermination de la personne exacte dont nous parlons en recherchant des informations autres que le 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 étudiants. Cependant, il deviendra de plus en plus difficile de trouver un unique, significatif et facile à retenir nom pour chaque enfant dans une école, une ville, un pays ou le monde entier. Un autre problème pour donner à chaque enfant un nom unique est que le processus permettant de déterminer si une autre personne a également nommé son enfant Macey, Maci ou Macie pourrait être très fatiguant..
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 allez apprendre à connaître les espaces de noms, leur importance et la résolution de leur portée en Python..
Un espace de noms est fondamentalement un système permettant de s'assurer que tous les noms d'un programme sont uniques et peuvent être utilisés sans aucun conflit. Vous savez peut-être déjà que tout ce qui se trouve dans Python, tel que des chaînes, des listes, des fonctions, etc., est un objet. Un autre fait intéressant est que Python implémente les espaces de noms en tant que dictionnaires. Il existe un mappage de nom en objet, avec les noms en tant que clés et les objets en tant que valeurs. Plusieurs espaces de noms peuvent utiliser le même nom et le mapper sur un objet différent. Voici quelques exemples d'espaces de noms:
Dans la série Modules mathématiques en 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é consiste à les préfixer avec le nom du module, comme math.log10 ()
et cmath.log10 ()
.
Les espaces de noms nous aident à identifier de manière unique tous les noms dans un programme. Cependant, cela ne signifie pas que nous pouvons utiliser un nom de variable n'importe où. 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 portées dans un programme. Voici une liste de certaines portées pouvant exister lors de l'exécution d'un programme.
Dans les prochaines sections de ce didacticiel, nous utiliserons largement la fonction intégrée dir () Python 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 sa portée..
Comme je l'ai mentionné dans la section précédente, la recherche d'un nom commence à partir de la fonction la plus profonde, puis continue de plus en plus jusqu'à ce que le programme puisse mapper ce nom sur un objet. Si aucun nom de ce type n’est trouvé dans l’un des espaces de noms, le programme lève un NameError exception.
Avant de commencer, essayez de taper dir ()
dans IDLE ou tout autre IDE Python.
dir () # ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']
Tous ces noms listés par dir ()
sont disponibles dans tous les programmes Python. Par souci de brièveté, je commencerai par les désigner par '__builtins __'… '__spec__'
dans le reste des exemples.
Voyons la sortie du dir ()
fonction après avoir défini une variable et une fonction.
a_num = 10 dir () # ['__builtins __'… '__spec__', 'a_num'] def some_func (): b_num = 11 print () () (()) some_func () # ['b_num'] dir () # ['__builtins__ '…' __Spec__ ',' a_num ',' some_func ']
le dir ()
function n’affiche que la liste des noms dans la portée actuelle. C’est pourquoi, dans le cadre de un_fonc ()
, il n'y a qu'un seul nom appelé b_num
. Appel dir ()
après avoir défini un_fonc ()
l'ajoute à la liste des noms disponibles dans l'espace de noms global.
Voyons maintenant la liste des noms dans certaines fonctions imbriquées. Le code dans ce bloc continue à partir du bloc précédent.
def outer_func (): c_num = 12 def inner_func (): d_num = 13 print (dir (), '- noms dans inner_func') e_num = 14 inner_func () print (dir (), '- noms dans outer_func') outer_func ( ) # ['d_num'] - noms dans inner_func # ['c_num', 'e_num', 'inner_func'] - noms dans outer_func
Le code ci-dessus définit deux variables et une fonction dans la portée de outer_func ()
. À l'intérieur inner_func ()
, la dir ()
fonction n'imprime que le nom d_num
. Cela semble juste comme d_num
est la seule variable définie ici.
Sauf spécification 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 d'après le code suivant.
a_num = 10 b_num = 11 def outer_func (): global a_num a_num = 15 b_num = 16 def inner_func (): global a_num = 20 b_num = 21 print ('a_num inside inner_func:', a_num) print ('b_num inside ', b_num) inner_func () print (' a_num inside outer_func: ', a_num) print (' b_num inside outer_func: ', b_num) outer_func () print (' a_num en dehors de toutes les fonctions: ', a_num) en print, fonctions: ', b_num) # a_num inside inner_func: 20 # b_num in inner_func: 21 # a_num in outer_func: 20 # b_num in outer_func: 16 # a_num en dehors de toutes les fonctions: 20 # b_num en dehors de toutes les fonctions: 11
À l'intérieur des deux outer_func ()
et inner_func ()
, un_num
a été déclaré être une variable globale. Nous sommes en train de définir une valeur différente pour la même variable globale. C’est la raison pour laquelle la valeur de un_num
sur tous les sites est de 20. Par ailleurs, chaque fonction crée sa propre b_num
variable avec une portée locale, et la impression()
la fonction affiche la valeur de cette variable à portée locale.
Il est très courant d'importer des modules externes dans vos projets pour accélérer le développement. Il existe trois manières différentes d'importer des modules. Dans cette section, vous apprendrez toutes ces méthodes, en discutant en détail de leurs avantages et inconvénients..
à partir du 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 directement une fonction sans ajouter le nom du module en tant que 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:dir () # ['__builtins __'… '__spec__'] de math import * dir () # ['__builtins __'… '__spec__', 'acos', 'acosh', 'asin', 'asinh', # 'atan' , 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degree', # 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', # 'frexp', 'fsum', 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', # 'isinf', 'isnan', 'ldexp', 'lgamma', 'log', 'log10', 'log1p', 'log2', # 'modf', 'nan', 'pi', 'pow', ' radians ',' sin ',' sinh ',' sqrt ',' tan ', #' tanh ',' trunc '] log10 (125) # 2.0969100130080562 depuis cmath import * dir () # [' __builtins __ '…' __spec__ ' , 'acos', 'acosh', 'asin', 'asinh', 'atan', # 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrés', 'e', 'erf', # 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp', 'fsum', # 'gamma', 'gcd', 'hypot', 'inf', 'isclose', 'isfinite', 'isinf', 'isnan', # 'ldexp', 'lgamma', 'log', 'log10', 'log1p', ' log2 ',' modf ',' nan ',' phase ', #' pi ',' polaire ',' pow ',' radians ',' re ct ',' sin ',' sinh ',' sqrt ',' tan ',' tanh ', #' trunc '] log10 (125) # (2.0969100130080562 + 0j)
Si vous connaissez le math et cmath modules, vous savez déjà que quelques noms communs sont définis dans ces deux modules mais s'appliquent respectivement à des nombres réels et complexes.
Depuis que nous avons importé le cmath module après la math module, il écrase les définitions de fonction de ces fonctions communes à partir du math module. C'est pourquoi le premier log10 (125)
renvoie un nombre réel et le second log10 (125)
renvoie un nombre complexe. Il n’est pas possible pour vous d’utiliser le log10 ()
fonction du module de maths 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 manière d'importer des fonctions de différents modules juste pour enregistrer quelques frappes au clavier.
à partir du module import nameA, nameB
Si vous savez que vous n'utiliserez qu'un ou deux noms d'un module, vous pouvez les importer directement à l'aide de cette méthode. De cette façon, vous pouvez écrire le code de manière plus concise tout en minimisant la pollution de l'espace de noms. Cependant, gardez à l’esprit que vous ne pouvez toujours utiliser aucun autre nom du module en utilisant module.nomZ
. Toute fonction portant le même nom dans votre programme écrasera également la définition de cette fonction importée du module. Cela rendra la fonction importée inutilisable. Voici un exemple d'utilisation de cette méthode:dir () # ['__builtins __'… '__spec__'] de l'importation mathématique log2, log10 dir () # ['__builtins __'… '__spec__', 'log10', 'log2'] log10 (125) # 2.0969100130080562
module d'importation
: 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 des espaces de noms et définir des fonctions dont le nom correspond au nom des fonctions du module..dir () # ['__builtins __'… '__spec__'] import math dir () # ['__builtins __'… '__spec__', 'maths]] math.log10 (125) # 2.0969100130080562
J'espère que ce tutoriel vous a aidé à comprendre les espaces de noms et leur importance. Vous devriez maintenant être capable de déterminer la portée de différents noms dans un programme et d’éviter les pièges potentiels..
De plus, n'hésitez pas à voir ce que nous avons disponible à la vente 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 traite des différentes manières d’importer des modules en Python et des avantages et inconvénients de chacun d’eux. Si vous avez des questions sur ce sujet, merci de me le faire savoir dans les commentaires..
Apprenez Python avec notre guide complet de tutoriel sur Python, que vous soyez débutant ou que vous soyez un codeur chevronné cherchant à acquérir de nouvelles compétences..