Python-lukninger: Hvordan bruges det, og hvorfor?

I denne vejledning lærer du om Python-lukning, hvordan man definerer en lukning og årsagerne til, at du skal bruge den.

Ikke-lokal variabel i en indlejret funktion

Før vi går ind i, hvad en lukning er, skal vi først forstå, hvad en indlejret funktion og ikke-lokal variabel er.

En funktion defineret i en anden funktion kaldes en indlejret funktion. Indlejrede funktioner har adgang til variabler i det vedlagte område.

I Python er disse ikke-lokale variabler skrivebeskyttet som standard, og vi skal erklære dem eksplicit som ikke-lokale (ved hjælp af ikke-lokalt nøgleord) for at ændre dem.

Følgende er et eksempel på en indlejret funktion, der får adgang til en ikke-lokal variabel.

 def print_msg(msg): # This is the outer enclosing function def printer(): # This is the nested function print(msg) printer() # We execute the function # Output: Hello print_msg("Hello")

Produktion

 Hej

Vi kan se, at den indlejrede printer()funktion var i stand til at få adgang til den ikke-lokale msg-variabel for den indesluttende funktion.

Definition af en lukningsfunktion

I eksemplet ovenfor, hvad ville der ske, hvis den sidste linje i funktionen print_msg()returnerede printer()funktionen i stedet for at kalde den? Dette betyder, at funktionen blev defineret som følger:

 def print_msg(msg): # This is the outer enclosing function def printer(): # This is the nested function print(msg) return printer # returns the nested function # Now let's try calling this function. # Output: Hello another = print_msg("Hello") another()

Produktion

 Hej

Det er usædvanligt.

Den print_msg()funktion blev kaldt med strengen "Hello"og den returnerede funktion var bundet til navnet en anden. Ved opkald another()blev meddelelsen stadig husket, selvom vi allerede var færdige med at udføre print_msg()funktionen.

Denne teknik, hvormed nogle data ( "Helloi dette tilfælde) bliver knyttet til koden, kaldes lukning i Python .

Denne værdi i det vedlagte område huskes, selv når variablen går uden for omfanget, eller selve funktionen fjernes fra det aktuelle navneområde.

Prøv at køre følgende i Python-skalen for at se output.

 >>> del print_msg >>> another() Hello >>> print_msg("Hello") Traceback (most recent call last):… NameError: name 'print_msg' is not defined

Her fungerer den returnerede funktion stadig, selv når den oprindelige funktion blev slettet.

Hvornår har vi lukninger?

Som det ses af ovenstående eksempel, har vi en lukning i Python, når en indlejret funktion refererer til en værdi i dens vedlagte omfang.

Kriterierne, der skal være opfyldt for at skabe lukning i Python, er opsummeret i de følgende punkter.

  • Vi skal have en indlejret funktion (funktion inde i en funktion).
  • Den indlejrede funktion skal henvise til en værdi, der er defineret i den vedlagte funktion.
  • Den indesluttende funktion skal returnere den indlejrede funktion.

Hvornår skal man bruge lukninger?

Så hvad er lukninger gode til?

Lukninger kan undgå brugen af ​​globale værdier og giver en eller anden form for dataskydning. Det kan også give en objektorienteret løsning på problemet.

Når der er få metoder (en metode i de fleste tilfælde), der skal implementeres i en klasse, kan lukninger give en alternativ og mere elegant løsning. Men når antallet af attributter og metoder bliver større, er det bedre at implementere en klasse.

Her er et simpelt eksempel, hvor en lukning kan være mere at foretrække end at definere en klasse og lave objekter. Men præferencen er helt din.

 def make_multiplier_of(n): def multiplier(x): return x * n return multiplier # Multiplier of 3 times3 = make_multiplier_of(3) # Multiplier of 5 times5 = make_multiplier_of(5) # Output: 27 print(times3(9)) # Output: 15 print(times5(3)) # Output: 30 print(times5(times3(2)))

Produktion

 27 15 30

Python Decorators gør også en udstrakt brug af lukninger.

På en afsluttende note er det godt at påpege, at de værdier, der bliver lukket i lukningsfunktionen, kan findes.

Alle funktionsobjekter har en __closure__attribut, der returnerer en tuple af celleobjekter, hvis det er en lukningsfunktion. Med henvisning til eksemplet ovenfor kender vi times3og times5er lukningsfunktioner.

 >>> make_multiplier_of.__closure__ >>> times3.__closure__ (,)

Celleobjektet har attributten celleindhold, der gemmer den lukkede værdi.

 >>> times3.__closure__(0).cell_contents 3 >>> times5.__closure__(0).cell_contents 5

Interessante artikler...