A Pythonban számos alkalmazási formában találkozhatunk closure függvényekkel. Ezen alapulnak például a dekorátorok, amelyek a Python jellegzetes, hasznos, és ezért gyakran használt nyelvi szerkezetei.
Az olyan függvényeket, amelyeket egy másik függvényen belül hoztunk létre és e körülzáró függvény visszatérési értékeként kapunk closure függvénynek nevezzük. Ennek jellemzője nem csak az, hogy egy másik függvényben van definiálva, hanem az, hogy
1) a körülzáró függvényen kívül is elérhető még akár olyankor is, ha a körülzáró függvény már nem is létezik.
2) mintegy össze van zárva a létrehozó környezetével (innen az elnevezés eredete), ami azt jelenti, hogy a körülzáró függvény belső lokális változóihoz akkor is hozzáfér, ha a vezérlés már nincs a körülzáró függvényen.
Ez olyan, mintha a closure függvénynek emlékezete lenne, vagyis nem számít, hogy a programvezérlés kikerült a körülzáró függvényből, mert a lokális változói értékének emléke megmarad a closure számára, annak minden egyes hívásakor használhatóan, függetlenül attól, hogy hol és hányszor hívjuk meg a programkódban.
Hasonlatos egy kicsit a closure egy katonai bázisban állomásozó katonához, aki bárhol a bázison kívül bevethető, és az akció helyszínére a bázison biztosított eszközöket a hátizsákjában mindig magával tudja vinni.

Nézzünk most egy egyszerű, szemléltető példaalkalmazást is.
A feladat legyen az, hogy egy étterem asztalonkénti fogyasztását kell az egyes rendelések után folyamatosan nyilvántartani. Két menüt kínál az étterem, amiből a vendégek hétköznap és hétvégén egy-egy asztálnál választhatnak. Ha egy adott asztalnál a vendég befejezte és fizetne, akkor meg kell tudni mondani a végösszeget. De, ha menet közben rákérdez az addigi költésre azt is meg kell tudni adni.
A feladatot több módon is meg lehet oldani. Most mi closure függvénnyel tesszük ezt meg. Az alábbiakban láthatjuk a program teljes kódját.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
menü1 = dict(gulyásleves=2150, gombaleves=2730, pacalpörkölt=3690, bécsiszelet=3190, fagylalt=1280, somlói_galuska=1450) menü2 = dict(halászlé=2950, tatárbeefsteak=3940, vegatál=2740, grillsajt=2100, aranygaluska=1490, torta=860) def fogyasztás(étlap): étel_árak = [] def összegző(étel: str = ''): étel_árak.append(étlap.get(étel, 0)) return sum(étel_árak) return összegző # Két asztalnál rendelnek a vendégek az adott napi menüből. # A pincér megnyitja a két asztal számláját. asztal1 = fogyasztás(menü1) asztal2 = fogyasztás(menü1) # Leves és előétel fogyasztások. asztal1('gulyásleves') asztal2('gombaleves') # Főétel fogyasztás. asztal1('pacalpörkölt') asztal2('bécsiszelet') # Desszert fogyasztás. asztal1('fagylalt') asztal2('somlói_galuska') # Fizetés print(f'1. asztal számlaösszeg: {asztal1()} Ft.') print(f'2. asztal számlaösszeg: {asztal2()} Ft.') # Eredmény: # 1. asztal számlaösszeg: 7120 Ft. # 2. asztal számlaösszeg: 7370 Ft. |
Két szótárban tároljuk a kínált ételeket és azok árát. A fogyasztás nevű függvény argumentuma e szótárak valamelyikét fogadja. E körülzáró függvényen belül egy összegző nevű függvényt definiálunk, amelynek a rendelt és fogyasztott étel nevét kell argumentumként megadni. Az étel, valamint a körülzáró függvény argumentumában megkapott menü alapján meghatározzuk az árat, amit az étel_árak listában tárolunk. Az összegző függvény e lista aktuális összegét adja vissza. A körülzáró függvény pedig az összegző függvényobjektummal tér vissza.
Tegyük fel, hogy két asztalhoz érkeznek vendégek. Ezért a fogyasztás függvényt kétszer meghívjuk az aktuális menüvel. Az így létrejövő asztal1 és asztal2 két closure függvény. A rendelések a szokásos fázisokban történnek (előétel, főétel, desszert). Minden új étel rendelésénél a megfelelő closure függvényt meghívjuk a fogyasztott étellel. A végén pedig kiírjuk a fizetendő összegeket.
A megoldás előnye, hogy átlátható és rugalmas kódot eredményez. Ez utóbb azt jelenti, hogy ha újabb vendég érkezik egy új asztalhoz, akkor nem kell a már meglévő kódokba belenyúlni, hanem csak egyszerűen bővíteni a programot az előzőek mintájára.
E témával ennél sokkal részletesebben foglalkozik a Python tudásépítés lépésről lépésre című e-könyv „Környezetükkel egységbe forrt függvények – closures” című fejezete.