Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Каррирование (Currying)
Каррирование — это функциональный прием, который преобразует функцию с несколькими параметрами в последовательность функций с одним параметром каждая. Названо в честь математика Хаскелла Карри.
Концепция
Вместо функции, которая принимает все аргументы сразу:
# Обычная функция с тремя параметрами
def add(a, b, c):
return a + b + c
result = add(1, 2, 3) # 6
Каррированная версия работает так:
# Каррированная функция
def curry_add(a):
def inner_add(b):
def inner_inner_add(c):
return a + b + c
return inner_inner_add
return inner_add
# Использование
result = curry_add(1)(2)(3) # 6
Как это работает
- Вызываем функцию с первым аргументом:
curry_add(1) - Возвращается новая функция, которая "помнит" первый аргумент
- Вызываем новую функцию со вторым аргументом:
(2) - Возвращается еще одна функция, которая "помнит" первые два аргумента
- Вызываем финальную функцию с третьим аргументом:
(3) - Получаем результат
Это работает благодаря замыканиям (closures) — внутренние функции помнят значения внешних переменных.
Практические примеры
1. Простое каррирование вручную
def multiply(a):
def inner(b):
return a * b
return inner
multiply_by_2 = multiply(2)
multiply_by_3 = multiply(3)
print(multiply_by_2(5)) # 10
print(multiply_by_3(5)) # 15
Мы создали специализированные функции! Это частичное применение (partial application).
2. Каррирование с помощью decorators
def curry(func):
def curried(*args, **kwargs):
if len(args) + len(kwargs) >= func.__code__.co_argcount:
return func(*args, **kwargs)
else:
return lambda *args2, **kwargs2: curried(
*(args + args2), **(kwargs | kwargs2)
)
return curried
@curry
def add(a, b, c):
return a + b + c
print(add(1, 2, 3)) # 6
print(add(1)(2)(3)) # 6
print(add(1, 2)(3)) # 6
print(add(1)(2, 3)) # 6
3. Использование functools.partial (похоже на каррирование)
from functools import partial
def power(base, exponent):
return base ** exponent
# Создаем специализированную функцию
square = partial(power, exponent=2)
cube = partial(power, exponent=3)
print(square(5)) # 25
print(cube(5)) # 125
Разница: partial() применяет несколько аргументов сразу, а каррирование — один аргумент за раз.
Реальные примеры
1. Фильтрация списков
def is_greater_than(threshold):
def check(value):
return value > threshold
return check
greater_than_5 = is_greater_than(5)
greater_than_10 = is_greater_than(10)
numbers = [1, 5, 8, 10, 15]
print(list(filter(greater_than_5, numbers))) # [8, 10, 15]
print(list(filter(greater_than_10, numbers))) # [10, 15]
2. Конфигурация логгера
def create_logger(level):
def log(message):
print(f"[{level}] {message}")
return log
error_log = create_logger("ERROR")
info_log = create_logger("INFO")
warning_log = create_logger("WARNING")
error_log("Something went wrong") # [ERROR] Something went wrong
info_log("App started") # [INFO] App started
warning_log("Be careful") # [WARNING] Be careful
3. Валидация данных
def validator(min_value, max_value):
def validate(value):
if min_value <= value <= max_value:
return True
return False
return validate
validate_age = validator(0, 150)
validate_score = validator(0, 100)
print(validate_age(25)) # True
print(validate_age(200)) # False
print(validate_score(85)) # True
print(validate_score(150)) # False
4. Запросы к API с предустановками
import requests
def create_api_request(base_url, api_key):
def request(endpoint, params=None):
headers = {"Authorization": f"Bearer {api_key}"}
url = f"{base_url}/{endpoint}"
return requests.get(url, headers=headers, params=params)
return request
# Создаем специализированные функции
api_github = create_api_request("https://api.github.com", "token123")
api_twitter = create_api_request("https://api.twitter.com", "token456")
# Используем
api_github("users/torvalds")
api_twitter("tweets")
Преимущества каррирования
✅ Переиспользование — создавай специализированные функции из общих ✅ Композиция — легко комбинировать функции ✅ Функциональное программирование — соответствует парадигме FP ✅ Чистота — функции без побочных эффектов
Недостатки
❌ Сложность — код может быть сложнее для понимания ❌ Производительность — каждый вызов создает новую функцию ❌ Многословность — требует больше кода
Когда использовать
- Event handlers — создание обработчиков с параметрами
- Фильтры и трансформеры — работа с коллекциями
- Конфигурация — создание функций с предустановками
- Декораторы — оборачивание функций
Заключение
Каррирование — это элегантный способ работы с функциями в функциональном программировании. Хотя Python не имеет встроенной поддержки каррирования (как Haskell или Lisp), мы можем реализовать его благодаря первоклассности функций и замыканиям. Используй его когда нужна гибкость и переиспользуемость функций.