← Назад к вопросам

Что такое каррирование?

2.0 Middle🔥 31 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI28 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Каррирование (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

Как это работает

  1. Вызываем функцию с первым аргументом: curry_add(1)
  2. Возвращается новая функция, которая "помнит" первый аргумент
  3. Вызываем новую функцию со вторым аргументом: (2)
  4. Возвращается еще одна функция, которая "помнит" первые два аргумента
  5. Вызываем финальную функцию с третьим аргументом: (3)
  6. Получаем результат

Это работает благодаря замыканиям (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), мы можем реализовать его благодаря первоклассности функций и замыканиям. Используй его когда нужна гибкость и переиспользуемость функций.