0Pricing
Coding Interview Prep · Lekcja

Funkcje, domknięcia i lambda

Zdefiniują Państwo wielokrotnego użytku funkcje pomocnicze, wykorzystają argumenty domyślne i zastosują wyrażenia lambda do sortowania oraz wzorców funkcyjnych w zadaniach rekrutacyjnych.

Funkcje, domknięcia i lambda to bezpłatna lekcja Coding Interview Prep na CoddyKit. To lekcja 4 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Coding Interview Prep, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.

Definiowanie funkcji w Pythonie

Funkcje w Pythonie są obiektami pierwszoklasowymi: można je przekazywać, zwracać i przechowywać. Dobrze nazwane funkcje pomocnicze zwiększają czytelność kodu na rozmowie rekrutacyjnej. Najpierw należy obsłużyć przypadki brzegowe.

def is_palindrome(s: str) -> bool:
    '''Return True if s reads the same forwards and backwards.'''
    s = s.lower()
    return s == s[::-1]

print(is_palindrome('Racecar'))  # True
print(is_palindrome('hello'))    # False

# Functions as values
checks = [is_palindrome]
print(checks[0]('level'))  # True

Argumenty domyślne i nazwane

Wartości domyślne pozwalają pomijać argumenty przy wywołaniu. Nie należy jednak nigdy używać modyfikowalnej wartości domyślnej, takiej jak lista — wszyscy wywołujący współdzielą wtedy tę samą wartość. Rozwiązanie polega na ustawieniu wartości domyślnej na None i utworzeniu listy wewnątrz funkcji. Szczegóły pokazano w kodzie.

# WRONG: shared mutable default
def bad_append(val, lst=[]):
    lst.append(val)
    return lst

print(bad_append(1))  # [1]
print(bad_append(2))  # [1, 2]  surprise!

# CORRECT: use None sentinel
def good_append(val, lst=None):
    if lst is None:
        lst = []
    lst.append(val)
    return lst

print(good_append(1))  # [1]
print(good_append(2))  # [2]

*args i **kwargs

*args zbiera dodatkowe argumenty pozycyjne w krotkę, a **kwargs zbiera dodatkowe argumenty nazwane w słownik. Gwiazdka * rozpakowuje również sekwencję podczas wywoływania funkcji.

def total(*args):
    return sum(args)

print(total(1, 2, 3))     # 6
print(total(1, 2, 3, 4))  # 10

# Unpack a list as positional args
point = [3, 7]
print(max(*point))   # 7

# **kwargs
def greet(**kwargs):
    name = kwargs.get('name', 'World')
    return f'Hello, {name}!'

print(greet(name='Alice'))  # Hello, Alice!

Wyrażenia lambda

lambda to niewielka, jednowierszowa funkcja: lambda params: expression. Doskonale nadaje się jako szybka funkcja key w sorted lub max. W przypadku większych konstrukcji czytelniejsza będzie nazwana funkcja def.

# Lambda as sort key
pairs = [(1, 3), (2, 1), (3, 2)]
sorted_by_second = sorted(pairs, key=lambda p: p[1])
print(sorted_by_second)  # [(2,1),(3,2),(1,3)]

# Lambda with map
double = list(map(lambda n: n * 2, [1, 2, 3]))
print(double)  # [2, 4, 6]

# Named function is clearer for complex logic
def sort_key(p):
    return (p[1], -p[0])  # secondary sort
print(sorted(pairs, key=sort_key))

Funkcje zagnieżdżone i domknięcia

Domknięcie to funkcja, która pamięta zmienne z otaczającej ją funkcji. Można zdefiniować funkcję pomocniczą wewnątrz innej funkcji, a wtedy będzie ona mogła korzystać ze zmiennych zewnętrznych — przydaje się to w DFS.

def make_counter(start=0):
    count = [start]  # list to allow mutation
    def increment():
        count[0] += 1
        return count[0]
    return increment

counter = make_counter()
print(counter())  # 1
print(counter())  # 2

# Alternative: nonlocal keyword
def make_counter2():
    count = 0
    def increment():
        nonlocal count
        count += 1
        return count
    return increment

Domknięcia w rekurencyjnym DFS

Typowy wzorzec polega na zdefiniowaniu funkcji pomocniczej dfs wewnątrz funkcji głównej i pozwoleniu jej na zbieranie wyników w zmiennej zewnętrznej. Funkcja wewnętrzna jest domknięciem obejmującym ten zakres.

def max_depth(root):
    '''Closure pattern for tree DFS.'''
    max_d = [0]  # mutable container for closure

    def dfs(node, depth):
        if node is None:
            return
        max_d[0] = max(max_d[0], depth)
        dfs(node.left, depth + 1)
        dfs(node.right, depth + 1)

    dfs(root, 1)
    return max_d[0]
# This pattern avoids a class or global state.

functools.lru_cache do memoizacji

lru_cache (lub @cache w wersji 3.9+) zapamiętuje wyniki funkcji na podstawie jej argumentów, zmieniając naiwną implementację ciągu Fibonacciego z O(2^n) na O(n). Argumenty muszą być haszowalne, dlatego należy używać krotek.

from functools import lru_cache

@lru_cache(maxsize=None)
def fib(n):
    if n <= 1:
        return n
    return fib(n - 1) + fib(n - 2)

print(fib(40))   # 102334155  fast!
print(fib.cache_info())  # hits, misses, size

Funkcje wyższego rzędu

Funkcja wyższego rzędu przyjmuje funkcję lub ją zwraca. Do tej kategorii należą sorted, map i filter. Tworzenie własnych funkcji tego rodzaju pozwala abstrahować powtarzalne wzorce. Kod pokazuje kompozycję.

def apply_twice(f, x):
    return f(f(x))

print(apply_twice(lambda n: n * 2, 3))  # 12  (3*2*2)

# Composing transformations
def compose(f, g):
    return lambda x: f(g(x))

double = lambda n: n * 2
add_one = lambda n: n + 1
double_then_add = compose(add_one, double)
print(double_then_add(5))  # 11  ((5*2)+1)

Rekurencja z funkcjami pomocniczymi

Wiele rozwiązań łączy funkcję zewnętrzną, która zajmuje się przygotowaniem danych i przypadkami brzegowymi, z wewnętrzną funkcją helper, która wykonuje rekurencję. Zapewnia to przejrzysty publiczny interfejs i odizolowaną logikę. Szczegóły pokazano w kodzie.

def flatten(nested):
    '''Flatten an arbitrarily nested list.'''
    result = []

    def _flatten(lst):
        for item in lst:
            if isinstance(item, list):
                _flatten(item)
            else:
                result.append(item)

    _flatten(nested)
    return result

print(flatten([1, [2, [3, 4], 5], 6]))
# [1, 2, 3, 4, 5, 6]

Funkcje częściowe z functools.partial

functools.partial wstępnie wypełnia niektóre argumenty i zwraca nowy obiekt wywoływalny. Przydaje się, gdy interfejs API wymaga funkcji bez argumentów, ale potrzebny jest jeden ustalony parametr.

from functools import partial

def power(base, exp):
    return base ** exp

square = partial(power, exp=2)
cube   = partial(power, exp=3)

print(square(5))   # 25
print(cube(3))     # 27
print(list(map(square, [1, 2, 3, 4])))  # [1, 4, 9, 16]

Lambda dla własnych komparatorów

Python 3 usunął komparatory przyjmujące dwa argumenty, ale cmp_to_key przywraca je na potrzeby skomplikowanego porządkowania — na przykład ustawiania liczb tak, aby ich konkatenacja była największa. Szczegóły pokazano w kodzie.

from functools import cmp_to_key

def largest_number(nums):
    def compare(a, b):
        if a + b > b + a: return -1
        if a + b < b + a: return 1
        return 0
    strs = list(map(str, nums))
    strs.sort(key=cmp_to_key(compare))
    result = ''.join(strs)
    return '0' if result[0] == '0' else result

print(largest_number([3, 30, 34, 5, 9]))  # '9534330'

Szybki sprawdzian

Szybki sprawdzian — proszę pokazać, czego udało się nauczyć o funkcjach, domknięciach i lambdach. Proszę nabrać oddechu i zaczynać. 🚀

Podsumowanie lekcji

Podsumowanie: nigdy nie należy używać modyfikowalnych wartości domyślnych (należy używać None), domknięcia pozwalają wewnętrznym funkcjom pomocniczym sięgać do zmiennych zewnętrznych podczas DFS, a narzędzia functools, takie jak lru_cache, umożliwiają tworzenie szybkich rozwiązań.

Często zadawane pytania

Czy lekcja „Funkcje, domknięcia i lambda” jest bezpłatna?

Tak — pełny tekst „Funkcje, domknięcia i lambda” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Coding Interview Prep, przejdź na CoddyKit PRO. Kurs Coding Interview Prep zawiera 4 lekcji w sumie.

Co nauczysz się w „Funkcje, domknięcia i lambda”?

Zdefiniują Państwo wielokrotnego użytku funkcje pomocnicze, wykorzystają argumenty domyślne i zastosują wyrażenia lambda do sortowania oraz wzorców funkcyjnych w zadaniach rekrutacyjnych. Ćwiczysz Coding Interview Prep z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Coding Interview Prep?

Nie wymagamy żadnego doświadczenia. Coding Interview Prep w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 4 z 4.

Ile czasu zajmuje lekcja „Funkcje, domknięcia i lambda”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Coding Interview Prep?

Tak. Każda lekcja Coding Interview Prep zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Listy, krotki i wycinki
  2. Słowniki i zbiory w Pythonie
  3. Wyrażenia składane i funkcje wbudowane
  4. Funkcje, domknięcia i lambda
← Powrót do Coding Interview Prep