Приёмы функционального программирования
Что такое замыкание?
подробнее
Замыкание (closure) — это функция, которая запоминает значения из enclosure (охватывающей/внешней) области видимости, даже когда она вызывается вне этой области.
Пример:
def outer_function(x):
def inner_function(y):
return x + y # x берется из внешней области видимости
return inner_function
# Создаем замыкание
closure = outer_function(10)
result = closure(5) # 15
Примеры использования:
Фабрика функций:
def make_multiplier(n):
def multiplier(x):
return x * n
return multiplier
double = make_multiplier(2)
triple = make_multiplier(3)
print(double(5)) # 10
print(triple(5)) # 15
Сохранение состояний:
def counter():
count = 0
def increment():
nonlocal count
count += 1
return count
return increment
my_counter = counter()
print(my_counter()) # 1
print(my_counter()) # 2
print(my_counter()) # 3
Особенности
- Переменные из внешней области сохраняются в
__closure__ - Используют nonlocal для изменения переменных внешней функции
- Более “легковесная” альтернатива классам для простых случаев
Что такое декоратор?
подробнее
Декоратор - это паттерн проектирования, предназначенный для подключения поведения к объекту. Т.е это некий объект который добавляет поведение другому объекту, без использования наследования.
В Python декоратор реализуется как функция, которая принимает другую функцию в качестве аргумента и возвращает новую функцию, расширяя или изменяя поведение исходной функции без её изменения.
Примеры:
# Базовая структура
from functools import wraps
def my_decorator(func):
@wraps(func) # Сохраняет метаданные оригинальной функции
def wrapper(*args, **kwargs):
# Код до вызова функции
result = func(*args, **kwargs)
# Код после вызова функции
return result
return wrapper
@my_decorator
def my_function():
pass
# Декоратор с параметрами
def repeat(times):
def decorator(func):
def wrapper(*args, **kwargs):
for _ in range(times):
result = func(*args, **kwargs)
return result
return wrapper
return decorator
@repeat(3)
def say_hello():
print("Hello!")
say_hello() # Вывод: Hello! Hello! Hello!
# Класс-декоратор
class CountCalls:
def __init__(self, func):
self.func = func
self.count = 0
def __call__(self, *args, **kwargs):
self.count += 1
print(f"Функция вызвана {self.count} раз")
return self.func(*args, **kwargs)
@CountCalls
def say_hello():
print("Hello!")
# Дкоратор для класса
def class_decorator(cls):
# Модифицируем класс
return cls # или возвращаем новый класс
@class_decorator
class MyClass:
pass
Что такое рекурсия?
подробнее
Рекурсия — это процесс, при котором функция вызывает саму себя для решения задачи.
Рекурсивная функция должна иметь:
- Базовый случай — условие остановки рекурсии
- Рекурсивный случай — вызов функции с измененными параметрами
Пример (вычисление факториала):
# Обычная (итеративная функция)
def factorial_iterative(n):
result = 1
for i in range(1, n + 1):
result *= i
return result
print(factorial_iterative(5)) # 120
# Рекурсивная функция
def factorial_recursive(n):
# Базовый случай
if n == 0 or n == 1:
return 1
# Рекурсивный случай
return n * factorial_recursive(n - 1)
print(factorial_recursive(5)) # 120
Какие ограничения есть у рекурсии?
подробнее
Максимальная глубина рекурсии:
import sys
# Просмотр текущего лимита
print(sys.getrecursionlimit()) # Обычно 1000
# Изменение лимита (осторожно!)
sys.setrecursionlimit(2000)
Функции map, filter, reduce
подробнее
map()
map()применяет функцию к каждому элементу итерируемого объекта и возвращает итератор с результатами.
# синтаксис
map(function, iterable)
# пример (возведение в квадрат)
numbers = [1, 2, 3, 4, 5]
squared = list(map(lambda x: x**2, numbers))
print(squared) # [1, 4, 9, 16, 25]
filter()
filter()фильтрует элементы итерируемого объекта, оставляя только те, для которых функция возвращает True.
# синтаксис
filter(function, iterable)
# пример (фильтрация четных чисел)
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
even_numbers = list(filter(lambda x: x % 2 == 0, numbers))
print(even_numbers) # [2, 4, 6, 8, 10]
reduce()
reduce()применяет функцию кумулятивно к элементам итерируемого объекта, сводя его к единственному значению.
# синтаксис
from functools import reduce
reduce(function, iterable[, initializer])
# пример (сумма всех элементов)
numbers = [1, 2, 3, 4, 5]
total = reduce(lambda x, y: x + y, numbers)
print(total) # 15