Python Closures: Hvordan bruke det og hvorfor?

I denne opplæringen lærer du om Python-nedleggelse, hvordan du definerer en nedleggelse og årsakene til at du bør bruke den.

Ikke-lokal variabel i en nestet funksjon

Før vi går inn på hva en lukking er, må vi først forstå hva en nestet funksjon og ikke-lokal variabel er.

En funksjon definert i en annen funksjon kalles en nestet funksjon. Nestede funksjoner har tilgang til variabler i det vedlagte omfanget.

I Python er disse ikke-lokale variablene skrivebeskyttet som standard, og vi må erklære dem eksplisitt som ikke-lokale (ved hjelp av ikke-lokalt nøkkelord) for å endre dem.

Følgende er et eksempel på en nestet funksjon som får tilgang 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")

Produksjon

 Hallo

Vi kan se at den nestede printer()funksjonen var i stand til å få tilgang til den ikke-lokale msg-variabelen til den omsluttende funksjonen.

Definere en lukkingsfunksjon

I eksemplet ovenfor, hva ville skje hvis den siste linjen i funksjonen print_msg()returnerte printer()funksjonen i stedet for å ringe den? Dette betyr at funksjonen ble definert 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()

Produksjon

 Hallo

Det er uvanlig.

Den print_msg()funksjonen ble kalt med strengen "Hello"og returnert funksjonen ble bundet til navnet annen. Ved samtale another()ble meldingen fremdeles husket, selv om vi allerede var ferdig med å utføre print_msg()funksjonen.

Denne teknikken som noen data ( "Helloi dette tilfellet) blir knyttet til koden, kalles lukking i Python .

Denne verdien i det vedlagte omfanget huskes selv når variabelen går utenfor omfanget eller selve funksjonen blir fjernet fra det nåværende navneområdet.

Prøv å kjøre følgende i Python-skallet for å se utdataene.

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

Her fungerer den returnerte funksjonen fortsatt selv når den opprinnelige funksjonen ble slettet.

Når har vi stenginger?

Som sett fra eksemplet ovenfor, har vi en lukking i Python når en nestet funksjon refererer til en verdi i det vedlagte omfanget.

Kriteriene som må oppfylles for å opprette lukking i Python er oppsummert i følgende punkter.

  • Vi må ha en nestet funksjon (funksjon inne i en funksjon).
  • Den nestede funksjonen må referere til en verdi som er definert i den vedlagte funksjonen.
  • Den vedlagte funksjonen må returnere den nestede funksjonen.

Når skal du bruke stengninger?

Så hva er nedleggelser bra for?

Nedleggelser kan unngå bruk av globale verdier og gir en eller annen form for datagjemding. Det kan også gi en objektorientert løsning på problemet.

Når det er få metoder (en metode i de fleste tilfeller) som skal implementeres i en klasse, kan nedleggelser gi en alternativ og mer elegant løsning. Men når antall attributter og metoder blir større, er det bedre å implementere en klasse.

Her er et enkelt eksempel der en lukning kan være mer å foretrekke enn å definere en klasse og lage objekter. Men preferansen 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)))

Produksjon

 27 15 30

Python Decorators bruker også omfattende lukninger.

På en avsluttende merknad er det godt å påpeke at verdiene som blir lukket i lukkingsfunksjonen kan bli funnet ut.

Alle funksjonsobjekter har et __closure__attributt som returnerer en tuple av celleobjekter hvis det er en lukkingsfunksjon. Med henvisning til eksemplet ovenfor kjenner vi til times3og times5er lukkingsfunksjoner.

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

Celleobjektet har attributtet cell_contents som lagrer den lukkede verdien.

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

Interessante artikler...