Închideri Python: Cum se folosește și de ce?

În acest tutorial, veți afla despre închiderea Python, cum să definiți o închidere și motivele pentru care ar trebui să o utilizați.

Variabilă nelocală într-o funcție imbricată

Înainte de a intra în ceea ce înseamnă o închidere, trebuie să înțelegem mai întâi ce este o funcție imbricată și o variabilă nelocală.

O funcție definită în interiorul altei funcții se numește funcție imbricată. Funcțiile imbricate pot accesa variabile ale domeniului care conține.

În Python, aceste variabile non-locale sunt doar în citire în mod implicit și trebuie să le declarăm în mod explicit ca nelocale (folosind cuvânt cheie nonlocal) pentru a le modifica.

Următorul este un exemplu de funcție imbricată care accesează o variabilă nelocală.

 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")

Ieșire

 Buna ziua

Putem vedea că printer()funcția imbricată a putut accesa variabila msg non-locală a funcției de închidere.

Definirea unei funcții de închidere

În exemplul de mai sus, ce s-ar întâmpla dacă ultima linie a funcției ar print_msg()returna printer()funcția în loc să o apeleze? Aceasta înseamnă că funcția a fost definită după cum urmează:

 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()

Ieșire

 Buna ziua

E neobișnuit.

print_msg()Funcția a fost numită cu șirul , "Hello"iar funcția sa întors a fost legat la numele altuia. La apel another(), mesajul a fost încă amintit, deși am terminat deja executarea print_msg()funcției.

Această tehnică prin care unele date ( "Helloîn acest caz) sunt atașate la cod se numește închidere în Python .

Această valoare din domeniul de aplicare al conținutului este amintită chiar și atunci când variabila iese din domeniul de aplicare sau funcția în sine este eliminată din spațiul de nume curent.

Încercați să rulați următoarele în shell-ul Python pentru a vedea rezultatul.

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

Aici, funcția returnată încă funcționează chiar și atunci când funcția originală a fost ștearsă.

Când avem închideri?

După cum se vede din exemplul de mai sus, avem o închidere în Python atunci când o funcție imbricată face referire la o valoare în domeniul său de aplicare.

Criteriile care trebuie îndeplinite pentru a crea închiderea în Python sunt rezumate în următoarele puncte.

  • Trebuie să avem o funcție imbricată (funcție în interiorul unei funcții).
  • Funcția imbricată trebuie să se refere la o valoare definită în funcția de anexare.
  • Funcția de închidere trebuie să returneze funcția imbricată.

Când se utilizează închiderile?

Deci, la ce sunt bune închiderile?

Închiderile pot evita utilizarea valorilor globale și oferă o formă de ascundere a datelor. De asemenea, poate oferi o soluție orientată obiect asupra problemei.

Atunci când există puține metode (o metodă în majoritatea cazurilor) care trebuie implementate într-o clasă, închiderile pot oferi o soluție alternativă și mai elegantă. Dar când numărul de atribute și metode crește, este mai bine să implementați o clasă.

Iată un exemplu simplu în care o închidere ar putea fi mai preferabilă decât definirea unei clase și realizarea de obiecte. Dar preferința este a ta.

 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)))

Ieșire

 27 15 30

Decoratorii Python fac o utilizare extinsă și a închiderilor.

Într-o notă finală, este bine să subliniem că valorile care sunt incluse în funcția de închidere pot fi găsite.

Toate obiectele funcționale au un __closure__atribut care returnează un tuplu de obiecte celulare dacă este o funcție de închidere. Referindu-ne la exemplul de mai sus, cunoaștem times3și times5suntem funcțiile de închidere.

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

Obiectul celulă are atributul cell_contents care stochează valoarea închisă.

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

Articole interesante...