CodeGym /Kursy /Python SELF PL /Zamknięcia

Zamknięcia

Python SELF PL
Poziom 13 , Lekcja 3
Dostępny

3.1 Wprowadzenie do zamknięć

Zamknięcie to funkcja, która przechwytuje zmienne z otaczającego ją zakresu widoczności, nawet po tym, jak ten zakres zakończył swoje działanie. To oznacza, że zamknięcie może „pamiętać” wartości zmiennych z zewnętrznego zakresu widoczności i nadal z nimi pracować, nawet gdy ten zakres już nie działa.

Aby zrozumieć, jak działają zamknięcia, rozważmy następujący przykład:


def outer_function(x):
    def inner_function(y):
        return x + y

    return inner_function
    
closure = outer_function(10)
print(closure(5))  # Wyjście: 15

Zobaczmy, co tu się dzieje:

Funkcja zewnętrzna (outer_function): Ta funkcja przyjmuje argument x i definiuje wewnętrzną funkcję inner_function, która przyjmuje argument y i zwraca sumę x i y. Funkcja inner_function nie jest wywoływana wewnątrz outer_function, a jedynie deklarowana.

Funkcja wewnętrzna (inner_function): Ta funkcja jest zwracana z outer_function i zachowuje wewnętrznie referencję do wartości x, która została przekazana do outer_function.

Zamknięcie: Zmienna closure staje się zamknięciem, które „pamięta” wartość x (w tym przypadku 10) i może używać jej przy wywołaniu.

Najczęściej przy pierwszym kontakcie z zamknięciami jest trudno je zrozumieć. Więc spróbujmy zwiększyć Twoje zrozumienie zamknięć na przykładach.

3.2 Przykłady użycia zamknięć

Tworzenie funkcji-generatora

Zamknięcia mogą być używane do tworzenia funkcji-generatorów, które generują sekwencje wartości.


def make_counter():
    count = 0

    def counter():
        nonlocal count
        count += 1
        return count

    return counter
    
counter = make_counter()
print(counter())  # Wyjście: 1
print(counter())  # Wyjście: 2
print(counter())  # Wyjście: 3

Wyjaśnienie:

Funkcja-generator (make_counter): Ta funkcja tworzy zmienną count i zwraca wewnętrzną funkcję counter, która zwiększa wartość count i ją zwraca.

Zamknięcie: Funkcja counter zachowuje stan zmiennej count i może ją zmieniać przy każdym wywołaniu.

Tworzenie funkcji z konfiguracją

Zamknięcia mogą być użyte do tworzenia funkcji z wstępnie zdefiniowaną konfiguracją.


def make_multiplier(factor):
    def multiplier(x):
        return x * factor

    return multiplier
    
double = make_multiplier(2)
triple = make_multiplier(3)
    
print(double(5))  # Wyjście: 10
print(triple(5))  # Wyjście: 15

Wyjaśnienie:

Funkcja-konfigurator (make_multiplier): Ta funkcja przyjmuje mnożnik factor i zwraca wewnętrzną funkcję multiplier, która mnoży wejściową wartość przez factor.

Zamknięcia: Funkcje double i triple są zamknięciami, które przechowują swoje własne wartości factor i używają ich do mnożenia.

Filtrowanie danych z parametrami

Zamknięcia mogą być przydatne do tworzenia funkcji filtrujących z parametrami.


def make_filter(threshold):
    def filter_func(value):
        return value > threshold
        
    return filter_func
    
filter_above_10 = make_filter(10)
data = [5, 10, 15, 20]
filtered_data = list(filter(filter_above_10, data))
print(filtered_data)  # Wyjście: [15, 20]

Wyjaśnienie:

Funkcja-filtr (make_filter): Ta funkcja przyjmuje wartość progową threshold i zwraca wewnętrzną funkcję filter_func, która sprawdza, czy wartość przekracza próg.

Zamknięcie: Funkcja filter_func przechowuje wartość threshold i używa jej do filtrowania danych.

3.3 Plusy i minusy zamknięć

Zalety użycia zamknięć

Inkasulacja stanu: Zamknięcia pozwalają na inkapsulację stanu w funkcji, co pozwala uniknąć globalnych zmiennych i poprawia czytelność oraz stabilność kodu.

Elastyczność: Zamknięcia mogą być używane do tworzenia funkcji z pewną wymaganą konfiguracją lub zachowaniem, co czyni kod bardziej elastycznym i adaptacyjnym.

Programowanie funkcyjne: Zamknięcia są ważną koncepcją w programowaniu funkcyjnym, pozwalając na tworzenie funkcji wyższego rzędu i innych konstrukcji funkcyjnych.

Ograniczenia i potencjalne problemy

Mimo wielu zalet, zamknięcia mają też swoje ograniczenia:

Użycie pamięci: Zamknięcia mogą utrzymywać referencje do obiektów, które już nie są używane, co może prowadzić do wycieków pamięci.

Trudność w debugowaniu: Zamknięcia mogą skomplikować debugowanie kodu, ponieważ stan zmiennych może być nieoczywisty.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION