Python Closures: How to use and Why?

V tomto výučbe sa dozviete o ukončení Pythonu, o tom, ako definovať uzavretie, a o dôvodoch, prečo by ste ho mali používať.

Nelokálna premenná vo vnorenej funkcii

Predtým, ako sa dostaneme k záveru, musíme najskôr pochopiť, čo je vnorená funkcia a nelokálna premenná.

Funkcia definovaná vo vnútri inej funkcie sa nazýva vnorená funkcia. Vnorené funkcie majú prístup k premenným ohraničujúceho rozsahu.

V Pythone sú tieto nelokálne premenné predvolene iba na čítanie a aby sme ich mohli upraviť, musíme ich explicitne deklarovať ako nelokálne (pomocou nelokálneho kľúčového slova).

Nasleduje príklad vnorenej funkcie pristupujúcej k nelokálnej premennej.

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

Výkon

 Ahoj

Vidíme, že vnorená printer()funkcia dokázala získať prístup k nelokálnej premennej msg priloženej funkcie.

Definovanie funkcie uzavretia

Čo by sa stalo v príklade vyššie, čo by sa stalo, keby posledný riadok funkcie print_msg()vrátil printer()funkciu namiesto jej volania? To znamená, že funkcia bola definovaná takto:

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

Výkon

 Ahoj

To je neobvyklé.

print_msg()Funkcia bola volaná s reťazcom "Hello"a vracia funkcia bola viazaná na meno inej. Pri volaní another()bola správa stále zapamätaná, hoci sme už vykonávanie print_msg()funkcie dokončili .

Táto technika, pomocou ktorej sa niektoré údaje ( "Hellov tomto prípade) pripoja ku kódu, sa v Pythone nazýva uzávierka .

Táto hodnota v priloženom rozsahu sa pamätá, aj keď premenná vypadne z rozsahu alebo je samotná funkcia odstránená z aktuálneho priestoru mien.

Skúste spustiť nasledujúce v prostredí Python, aby ste videli výstup.

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

Tu vrátená funkcia stále funguje, aj keď bola pôvodná funkcia odstránená.

Kedy máme uzávery?

Ako je zrejmé z vyššie uvedeného príkladu, v Pythone máme uzávierku, keď vnorená funkcia odkazuje na hodnotu v jej obklopujúcom rozsahu.

Kritériá, ktoré musia byť splnené, aby sa vytvoril uzáver v Pythone, sú zhrnuté v nasledujúcich bodoch.

  • Musíme mať vnorenú funkciu (funkcia vo vnútri funkcie).
  • Vnorená funkcia musí odkazovať na hodnotu definovanú v priloženej funkcii.
  • Uzatváracia funkcia musí vrátiť vnorenú funkciu.

Kedy použiť uzávery?

Na čo sú teda dobré uzávery?

Uzávery sa môžu vyhnúť použitiu globálnych hodnôt a poskytujú určitú formu skrývania údajov. Môže tiež poskytnúť objektovo orientované riešenie problému.

Ak je v triede implementovaných niekoľko metód (vo väčšine prípadov jedna metóda), uzávery môžu poskytnúť alternatívne a elegantnejšie riešenie. Keď sa ale počet atribútov a metód zväčší, je lepšie implementovať triedu.

Tu je jednoduchý príklad, keď by uzavretie mohlo byť výhodnejšie ako definovanie triedy a vytváranie objektov. Ale preferencia je celá vaša.

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

Výkon

 27 15 30

Python Decorators taktiež vo veľkej miere využívajú uzávery.

Na záver je dobré poznamenať, že je možné zistiť hodnoty, ktoré sú obsiahnuté vo funkcii uzáveru.

Všetky funkčné objekty majú __closure__atribút, ktorý vráti n-ticu bunkových objektov, ak ide o uzatváraciu funkciu. Pokiaľ ide o vyššie uvedený príklad, poznáme times3a times5sú to funkcie zatvárania.

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

Objekt bunky má atribút cell_contents, ktorý uchováva uzavretú hodnotu.

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

Zaujímavé články...