Articles

Wat Zijn Python Namespaces (En Waarom Zijn Ze Nodig?)

naamconflicten komen voortdurend voor in het echte leven. Bijvoorbeeld, elke school waar ik ooit naar toe ging had ten minste twee studenten in mijn klas die dezelfde voornaam hadden. Als iemand in de klas kwam en om student X vroeg, zouden we enthousiast vragen: “over welke heb je het? Er zijn twee studenten met de naam X. ” daarna gaf de onderzoekende persoon ons een achternaam, en we stelden hem voor aan de juiste X.

al deze verwarring en het proces van het bepalen van de exacte persoon waar we het over hebben door te zoeken naar andere informatie dan een voornaam zou kunnen worden vermeden als iedereen een unieke naam had. Dit is geen probleem in een klas van 30 studenten. Het zal echter steeds moeilijker worden om een unieke, betekenisvolle en gemakkelijk te onthouden naam te bedenken voor elk kind in een school, Stad, Stad, Land of de hele wereld. Een ander probleem bij het verstrekken van elk kind een unieke naam is dat het proces van het bepalen of iemand anders heeft ook genoemd hun kind Macey, Maci of Macie kan zeer vermoeiend zijn.

een zeer vergelijkbaar conflict kan zich ook voordoen in het programmeren. Wanneer je een programma schrijft van slechts 30 regels zonder externe afhankelijkheden, is het heel gemakkelijk om unieke en betekenisvolle namen te geven aan al je variabelen. Het probleem doet zich voor als er duizenden regels in een programma zitten en je ook een aantal externe modules hebt geladen. In deze zelfstudie leert u over namespaces, hun belang en scope resolutie in Python.

Wat zijn naamruimten?

een naamruimte is in principe een systeem om ervoor te zorgen dat alle namen in een programma uniek zijn en zonder conflicten kunnen worden gebruikt. Je weet misschien al dat alles in Python-achtige strings, lijsten, functies, enz.- is een object. Een ander interessant feit is dat Python namespaces implementeert als woordenboeken. Er is een naam-tot-object toewijzing, met de namen als sleutels en de objecten als waarden. Meerdere naamruimten kunnen dezelfde naam gebruiken en deze toewijzen aan een ander object. Hier zijn een paar voorbeelden van namespaces:

  • lokale Namespace: Deze naamruimte bevat lokale namen in een functie. Deze naamruimte wordt gemaakt wanneer een functie wordt aangeroepen en duurt alleen totdat de functie terugkeert.
  • globale naamruimte: deze naamruimte bevat namen van verschillende geïmporteerde modules die u in een project gebruikt. Het wordt gemaakt wanneer de module is opgenomen in het project, en het duurt tot het script eindigt.
  • ingebouwde naamruimte: deze naamruimte bevat ingebouwde functies en ingebouwde namen voor uitzonderingen.

in de wiskundige Modules in de Python-serie over Envato Tuts+, schreef ik over nuttige wiskundige functies die beschikbaar zijn in verschillende modules. Bijvoorbeeld, de modules math en cmath hebben veel functies die voor beide dezelfde zijn, zoals log10()acos()cos()exp(), enz. Als u beide modules in hetzelfde programma gebruikt, is de enige manier om deze functies ondubbelzinnig te gebruiken door ze voor te voegen met de naam van de module, zoals math.log10() en cmath.log10().

Wat Is Scope?

naamruimten helpen ons alle namen in een programma uniek te identificeren. Dit betekent echter niet dat we een variabele naam kunnen gebruiken waar we maar willen. Een naam heeft ook een scope die de delen van het programma definieert waar u die naam kunt gebruiken zonder een voorvoegsel te gebruiken. Net als namespaces zijn er ook meerdere scopes in een programma. Hier is een lijst van een aantal scopes die kunnen bestaan tijdens de uitvoering van een programma.

  • een lokaal bereik, dat is het binnenste bereik dat een lijst met lokale namen bevat die beschikbaar zijn in de huidige functie.
  • een scope van alle ingesloten functies. De zoekopdracht naar een naam begint bij het dichtstbijzijnde omhullende bereik en gaat naar buiten.
  • een scope op moduleniveau die alle globale namen van de huidige module bevat.
  • het buitenste bereik dat een lijst van alle ingebouwde namen bevat. Deze scope wordt als laatste doorzocht om de naam te vinden waarnaar u verwijst.

in de volgende secties van deze tutorial zullen we uitgebreid gebruik maken van de ingebouwde Python dir() functie om een lijst met namen in de huidige lokale scope te retourneren. Dit zal u helpen het concept van namespaces en scope beter te begrijpen.

Scope Resolution

zoals ik al zei in de vorige sectie, begint het zoeken naar een gegeven naam vanuit de innermost functie en gaat dan hoger en hoger totdat het programma die naam kan toewijzen aan een object. Wanneer een dergelijke naam niet wordt gevonden in een van de namespaces, roept het programma een NameError uitzondering op.

voordat we beginnen, typ dir() in IDLE of een andere Python IDE.

dir()# 

laten we de uitvoer van de dir() functie bekijken na het definiëren van een variabele en een functie.

a_num = 10dir()# def some_func(): b_num = 11 print(dir()) some_func()# dir()# 

de functie dir() geeft alleen de lijst met namen binnen de huidige scope. Daarom is er binnen de scope van some_func() slechts één naam genaamd b_num. Het aanroepen van dir() na het definiëren van some_func() voegt het toe aan de lijst met namen die beschikbaar zijn in de Globale naamruimte.

laten we nu de lijst met namen bekijken binnen een aantal geneste functies. De code in dit blok gaat verder van het vorige blok.

de bovenstaande code definieert twee variabelen en een functie binnen het bereik van outer_func(). Binnen inner_func(), drukt de functie dir() alleen de naam d_numaf. Dit lijkt redelijk omdat d_num de enige variabele is die daarin gedefinieerd is.

tenzij expliciet opgegeven met global, maakt het opnieuw toewijzen van een globale naam in een lokale namespace een nieuwe lokale variabele met dezelfde naam. Dit blijkt uit de volgende code.

binnen zowel de outer_func() en inner_func()a_num is gedeclareerd als een globale variabele. We stellen gewoon een andere waarde in voor dezelfde globale variabele. Dit is de reden dat de waarde van a_num op alle locaties 20 is. Aan de andere kant maakt elke functie zijn eigen b_num variabele met een lokale scope, en de print() functie drukt de waarde van deze lokaal scoped variabele af.

modules correct importeren

Het is heel gebruikelijk om externe modules te importeren in uw projecten om de ontwikkeling te versnellen. Er zijn drie verschillende manieren om modules te importeren. In deze sectie, leert u over al deze methoden, bespreken hun voor-en nadelen in detail.

  • from module import *: Deze methode van het importeren van een module importeert alle namen uit de gegeven module direct in uw huidige naamruimte. Je zou geneigd kunnen zijn om deze methode te gebruiken omdat het je toestaat om een functie direct te gebruiken zonder de naam van de module als een voorvoegsel toe te voegen. Echter, het is zeer foutgevoelig, en je verliest ook de mogelijkheid om te vertellen welke module die functie daadwerkelijk geïmporteerd. Hier is een voorbeeld van het gebruik van deze methode:

Als u bekend bent met de math-en cmath-modules, weet u al dat er een paar algemene namen zijn die in beide modules zijn gedefinieerd, maar van toepassing zijn op respectievelijk reële en complexe getallen.

omdat we de CMATH-module na de math-module hebben geïmporteerd, overschrijft het de functiedefinities van deze gemeenschappelijke functies vanuit de math-module. Daarom geeft de eerste log10(125) een reëel getal terug en de tweede log10(125) een complex getal. Er is geen manier voor u om de log10() functie van de wiskunde module nu te gebruiken. Zelfs als u math.log10(125) probeerde te typen, krijgt u een NameError-uitzondering omdat math niet echt bestaat in de naamruimte.

De bottom line is dat je deze manier van het importeren van functies uit verschillende modules niet moet gebruiken alleen maar om een paar toetsaanslagen op te slaan.

  • from module import nameA, nameB: Als u weet dat u slechts één of twee namen uit een module gaat gebruiken, kunt u ze direct importeren met behulp van deze methode. Op deze manier kunt u de code beknopter schrijven terwijl u de vervuiling van de naamruimte tot een minimum beperkt. Houd er echter rekening mee dat u nog steeds geen andere naam uit de module kunt gebruiken door module.nameZte gebruiken. Elke functie die dezelfde naam heeft in uw programma zal ook de definitie van die functie die uit de module wordt geïmporteerd overschrijven. Dit maakt de geïmporteerde functie onbruikbaar. Hier is een voorbeeld van het gebruik van deze methode:
dir()# from math import log2, log10dir()# log10(125)# 2.0969100130080562
  • import module: Dit is de veiligste en aanbevolen manier om een module te importeren. Het enige nadeel is dat je de naam van de module moet voorvoegen in alle Namen die je gaat gebruiken in het programma. U zult echter in staat zijn om vervuiling van de naamruimte te voorkomen en ook functies te definiëren waarvan de namen overeenkomen met de naam van functies uit de module.
dir()# import mathdir()# math.log10(125)# 2.0969100130080562

Final Thoughts

Ik hoop dat deze tutorial u heeft geholpen namespaces en hun belang te begrijpen. U moet nu in staat zijn om de omvang van de verschillende namen in een programma te bepalen en te voorkomen dat potentiële valkuilen.

bovendien, aarzel niet om te zien wat we beschikbaar hebben voor verkoop en voor studie in de markt, en aarzel niet om vragen te stellen en uw waardevolle feedback te geven met behulp van de feed hieronder.

Het Laatste deel van het artikel besprak verschillende manieren om modules in Python te importeren en de voors en tegens van elk van hen. Als u vragen heeft met betrekking tot dit onderwerp, laat het me weten in de comments.

Leer Python

Leer Python met onze complete Python tutorial guide, of je nu net aan de slag bent of je een doorgewinterde programmeur bent die nieuwe vaardigheden wil leren.