Care sunt spațiile de nume Python (și de ce sunt necesare?)

Conflictele de nume se întâmplă tot timpul în viața reală. De exemplu, fiecare școală la care am mers vreodată a avut cel puțin doi studenți din clasa mea care au împărtășit același nume. Dacă cineva a intrat în clasă și a cerut elevului X, am întrebat cu entuziasm: "Despre care vorbești? Sunt doi studenți numiți X." După aceea, persoana care a cerut-o ne-ar da un nume de familie și i-am fi prezentat-o ​​la dreapta X.

Toată această confuzie și procesul de determinare a persoanei exacte despre care vorbim, prin căutarea altor informații în afară de un prim nume, ar putea fi evitate dacă fiecare are un nume unic. Aceasta nu este o problemă la o clasă de 30 de elevi. Cu toate acestea, va deveni din ce în ce mai greu să vină cu o unic, plin de înțeles și usor de amintit nume pentru fiecare copil dintr-o școală, oraș, oraș, țară sau întreaga lume. O altă problemă în a oferi fiecărui copil un nume unic este că procesul de a determina dacă altcineva și-a numit și copilul Macey, Maci sau Macie ar putea fi foarte obositor.

Un conflict foarte asemănător poate apărea și în programare. Când scrieți un program de doar 30 de linii fără dependență externă, este foarte ușor să dați nume unice și semnificative tuturor variabilelor. Problema apare când există mii de linii într-un program și ați încărcat și unele module externe. În acest tutorial, veți afla despre spațiul de nume, importanța și rezoluția domeniului în Python. 

Care sunt spațiile de nume?

Un spațiu de nume este, în esență, un sistem pentru a vă asigura că toate denumirile dintr-un program sunt unice și pot fi utilizate fără nici un conflict. S-ar putea să știți deja că totul în șiruri de caractere, liste, funcții etc., asemănătoare cu Python, este un obiect. Un alt fapt interesant este că Python implementează spațiile de nume ca dicționare. Există o mapare nume-la-obiect, cu numele ca chei și obiecte ca valori. Spațiul de nume multiplu poate utiliza același nume și îl poate mapa la un obiect diferit. Iată câteva exemple de spații de nume:

  • Spațiu Namespace: Acest spațiu de nume include nume locale în interiorul unei funcții. Acest spațiu de nume este creat atunci când este apelată o funcție și durează doar până când funcția revine.
  • Nota spațială globală: Acest spațiu de nume include nume din diferite module importate pe care le utilizați într-un proiect. Acesta este creat atunci când modulul este inclus în proiect și durează până la terminarea scenariului.
  • Spațiu de nume încorporat: acest spațiu de nume include funcții încorporate și nume excepționale încorporate.

În modulele matematice din seria Python despre Envato Tuts +, am scris despre funcțiile matematice utile disponibile în diferite module. De exemplu, modulele matematice și cmath au o mulțime de funcții comune celor două log10 (), acos (), cos (), exp (), etc Dacă utilizați ambele module în același program, singura modalitate de a utiliza aceste funcții fără ambiguitate este să le prefixați cu numele modulului, cum ar fi math.log10 () și cmath.log10 ().

Ce este Domeniul de aplicare??

Domeniile de nume ne ajută să identificăm în mod unic toate denumirile din cadrul unui program. Cu toate acestea, acest lucru nu implică faptul că putem folosi un nume de variabil oriunde vrem. Un nume are, de asemenea, un domeniu de aplicare care definește părțile programului în care ați putea utiliza acel nume fără a utiliza niciun prefix. La fel ca și spațiile de nume, există și mai multe domenii într-un program. Iată o listă a câtorva domenii care pot exista în timpul executării unui program.

  • Un domeniu de aplicare local, care este cel mai intim domeniu de aplicare care conține o listă de nume locale disponibile în funcția curentă.
  • Un domeniu al tuturor funcțiilor de închidere. Căutarea unui nume începe din cel mai apropiat domeniu de aplicare și se mișcă spre exterior.
  • Un domeniu de nivel al modulelor care conține toate numele globale din modulul curent.
  • Extinderea cea mai exterioară care conține o listă a tuturor denumirilor încorporate. Acest domeniu este căutat ultima pentru a găsi numele pe care l-ați referit. 

În secțiunile următoare din acest tutorial, vom folosi în mod extensiv funcția încorporată Python dir () pentru a returna o listă de nume în domeniul local actual. Acest lucru vă va ajuta să înțelegeți mai clar conceptul de spații de nume și de domeniu.

Domeniul de aplicare Rezoluție

Așa cum am menționat în secțiunea anterioară, căutarea unui nume dat începe de la cea mai interioară funcție și apoi se mișcă mai sus și mai mult până când programul poate cartografia acel nume unui obiect. Dacă niciun astfel de nume nu se găsește în nici unul dintre spațiile de nume, programul ridică a NameError excepție.

Înainte de a începe, încercați să tastați dir () în IDLE sau în orice alt IDE Python.

dir () # ['__builtins__', '__doc__', '__loader__', '__name__', '__package__', '__spec__']

Toate aceste nume enumerate de dir () sunt disponibile în fiecare program Python. Din motive de cointeresare, voi incepe sa ma refer la ele '__builtins __' ... '__spec__' în restul exemplelor.

Să vedem ieșirea din dir () funcție după definirea unei variabile și a unei funcții.

a_num = 10 dir () # ['__builtins __' ... '__spec__', 'a_num'] def some_func (): b_num = 11 print (dir '...' __spec__ ',' a_num ',' some_func '] 

dir () funcționează numai lista de nume din interiorul domeniului curent. De aceea, în interiorul domeniului some_func (), există doar un nume numit b_num. apel dir () după definire some_func () îl adaugă la lista de nume disponibile în spațiul de nume global.

Acum, să vedem lista de nume în interiorul unor funcții imbricate. Codul din acest bloc continuă din blocul anterior.

Definiți funcția extern_func (): c_num = 12 def interior_func (): d_num = 13 print (dir (), '- nume în inner_func') e_num = 14 inner_func ) # ['d_num'] - nume în inner_func # ['c_num', 'e_num', 'inner_func']] - nume în outer_func

Codul de mai sus definește două variabile și o funcție din interiorul domeniului outer_func (). Interior inner_func (), dir () funcția imprimă numai numele d_num. Acest lucru pare corect d_num este singura variabilă definită acolo.

Cu excepția cazului în care este specificat explicit prin utilizarea global, realocarea unui nume global în interiorul unui spațiu de nume local creează o nouă variabilă locală cu același nume. Acest lucru este evident din următorul cod.

a_num = 20 b_num = 11 def exterior_func (): global a_num a_num = 15 b_num = 16 def interior_func (): global a_num a_num = 20 b_num = 21 print ('a_num inside_func: ', b_num) inner_func () imprimare (' a_num in exterior_func: ', a_num) print (' b_num in exterior_func: Funcții: ', b_num) # a_num interior interior_func: 20 # b_num interior interior_func: 21 # a_num interior exterior_func: 20 # b_num interior exterior_func: 16 # a_num în afara tuturor funcțiilor: 20 #

În interiorul ambelor outer_func () și inner_func (), a_num a fost declarată a fi o variabilă globală. Vom stabili o valoare diferită pentru aceeași variabilă globală. Acesta este motivul pentru care valoarea a_num în toate locațiile este 20. Pe de altă parte, fiecare funcție creează propria sa funcție b_num variabilă cu un domeniu de aplicare local, și imprimare() funcția imprimă valoarea acestei variabile locale definite.

Importul corect al modulelor

Este foarte comună importul de module externe în proiectele dvs. pentru a accelera dezvoltarea. Există trei modalități diferite de a importa module. În această secțiune, veți afla despre toate aceste metode, discutând în detaliu argumentele pro și contra lor.

  • din importul modulelor *: Această metodă de importare a unui modul importează toate numele din modulul dat direct în spațiul dvs. de nume curent. S-ar putea să fiți tentat să utilizați această metodă deoarece vă permite să utilizați o funcție direct fără a adăuga numele prefixului. Cu toate acestea, este foarte predispusă la erori și, de asemenea, pierdeți capacitatea de a spune care modul a importat efectiv această funcție. Iată un exemplu de utilizare a acestei metode:
dir () # ['__builtins __' ... '__spec__'] de la math import * dir () # ['__builtins __' ... '__spec__', 'acos', 'acosh', 'asin' , 'atan2', 'atanh', 'ceil', 'copysign', 'cos', 'cosh', 'degrees', 'e', ​​'erf', 'erfc' "fabs", "fmod", "fxs", "fmod", "gx", "gcd", " 'log', 'log1', 'log2', 'modf', 'nan', 'pi', 'pow', 'isinf', 'isnan', 'ldexp', 'lgamma', 'log' ($) $ ($) $ ($) $ ($) $ ($) , 'acos', 'acosh', 'asin', 'asinh', 'atan', 'atan2', 'atanh', 'ceil', copysign, cos, cosh, 'e', 'erf', 'erfc', 'exp', 'expm1', 'fabs', 'factorial', 'floor', 'fmod', 'frexp' 'lgamma', 'log', 'log10', 'log1p', 'gcd', 'hypot','inf ',' isclose ','isfinite','isinf ',' log2 ',' modf ',' nan ',' faza ',' pi ',' polar ',' pow ',' radians ',' ct ',' sin ',' sinh ',' sqrt ',' tan ',' tanh ', #' trunc '] log10 (2.0969100130080562 +

Dacă sunteți familiarizat cu matematica și cmath module, deja știți că există câteva nume comune care sunt definite în ambele module, dar se aplică atât numerelor reale, cât și complexelor. 

Din moment ce am importat cmath modul după matematica modul, suprascrie definițiile funcțiilor acestor funcții comune de la matematica modul. Acesta este motivul pentru primul log10 (125) returnează un număr real, iar al doilea log10 (125) returnează un număr complex. Nu aveți cum să utilizați log10 () din modulul matematic acum. Chiar dacă ați încercat să tastați math.log10 (125), veți obține o excepție NameError pentru că matematica nu există de fapt în spațiul de nume.

Linia de jos este că nu ar trebui să utilizați acest mod de a importa funcții din diferite module doar pentru a salva câteva apăsări de taste.

  • din numele de import al modululuiA, nameB: Dacă știți că veți folosi doar unul sau două nume dintr-un modul, le puteți importa direct utilizând această metodă. În acest fel, puteți scrie codul mai concis, păstrând în același timp o reducere a poluării din spațiul de nume. Cu toate acestea, rețineți că încă nu puteți utiliza nici un alt nume din modul utilizând module.nameZ. Orice funcție care are același nume în program va suprascrie definiția acelei funcții importate din modul. Aceasta va face ca funcția importată să fie inutilizabilă. Iată un exemplu de utilizare a acestei metode:
dir () # ['__builtins __' ... '__spec__'] din logul log log2, log10 dir () # ['__builtins __' ... '__spec__', 'log10', log2 '] log10 (125) # 2.0969100130080562
  • modul de import: Aceasta este modalitatea cea mai sigură și recomandată de a importa un modul. Singurul dezavantaj este că va trebui să prefixați numele modulului cu toate denumirile pe care le veți folosi în program. Cu toate acestea, veți putea evita poluarea spațiului de nume și puteți defini, de asemenea, funcții ale căror nume se potrivesc cu numele funcțiilor din modul.
dir () # ['__builtins __' ... '__spec__'] import math dir () # ['__builtins __' ... '__spec__', 'math'] math.log10 (125) # 2.0969100130080562

Gândurile finale

Sper că acest tutorial te-a ajutat să înțelegi spațiile de nume și importanța lor. Acum ar trebui să puteți determina amploarea diferitelor denumiri ale unui program și să evitați capcanele potențiale. 

În plus, nu ezitați să vedeți ce avem la dispoziție pentru vânzare și pentru a studia pe piață și nu ezitați să întrebați orice întrebări și să furnizați feedback-ul valoros utilizând feedul de mai jos.

Secțiunea finală a articolului a discutat diferite moduri de a importa module în Python și argumentele pro și contra ale fiecăruia. Dacă aveți întrebări legate de acest subiect, vă rugăm să ne anunțați în comentarii.

Aflați Python

Aflați Python cu ghidul nostru complet de instrucțiuni Python, indiferent dacă sunteți doar începători sau sunteți un coder experimentat în căutarea unor noi abilități.

Cod