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')) # TrueArgumenty 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 incrementDomknię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, sizeFunkcje 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
- Listy, krotki i wycinki
- Słowniki i zbiory w Pythonie
- Wyrażenia składane i funkcje wbudowane
- Funkcje, domknięcia i lambda