📝 Python

Function Composition — Композиция функций

P
Автор
PyLand Team
📅
Опубликовано
03.04.2026
⏱️
Время чтения
3 мин
👁️
Просмотров
387
🌳
Уровень
Продвинутый

Композиция соединяет небольшие функции в цепочку, где результат одной функции становится аргументом следующей.

Что такое Function Composition?

Function Composition — это комбинирование простых функций в сложные.

В математике: (f ∘ g)(x) = f(g(x)) — сначала g, потом f.

def add_10(x):
    return x + 10

def multiply_2(x):
    return x * 2

# Композиция вручную: сначала add_10, потом multiply_2
result = multiply_2(add_10(5))
print(result)  # 30
# 5 → add_10 → 15 → multiply_2 → 30

Зачем нужна композиция?

Без композиции один и тот же pipeline повторяется вручную:

data1 = step1(raw_data)
data2 = step2(data1)
result = step3(data2)

# Для другого набора — опять:
data1 = step1(other_data)
data2 = step2(data1)
result = step3(data2)

С композицией — создаём pipeline один раз и переиспользуем:

process = pipe(step1, step2, step3)

result1 = process(raw_data)
result2 = process(other_data)
result3 = process(more_data)

compose() и pipe()

compose() — справа налево

def compose(*functions):
    """Применить функции справа налево: f(g(h(x)))."""
    def composed(x):
        result = x
        for func in reversed(functions):
            result = func(result)
        return result
    return composed

def add_10(x):
    return x + 10

def multiply_2(x):
    return x * 2

def square(x):
    return x ** 2

# compose: последний аргумент выполняется первым
pipeline = compose(square, multiply_2, add_10)
print(pipeline(5))  # 900
# 5 → add_10 → 15 → multiply_2 → 30 → square → 900

Читается справа налево (как в математике).

pipe() — слева направо

def pipe(*functions):
    """Применить функции слева направо."""
    def piped(x):
        result = x
        for func in functions:
            result = func(result)
        return result
    return piped

# pipe: первый аргумент выполняется первым
pipeline = pipe(add_10, multiply_2, square)
print(pipeline(5))  # 900
# 5 → add_10 → 15 → multiply_2 → 30 → square → 900

Читается слева направо — привычнее для кода.


Практические примеры

Пример 1: Очистка строк

import string

def trim(text):
    return text.strip()

def lowercase(text):
    return text.lower()

def remove_punctuation(text):
    return text.translate(str.maketrans("", "", string.punctuation))

clean_text = pipe(trim, lowercase, remove_punctuation)

dirty = "  Hello, World!  "
print(clean_text(dirty))  # "hello world"

Пример 2: Расчёт цены

def validate_positive(x):
    if x <= 0:
        raise ValueError("Must be positive")
    return x

def apply_discount(percent):
    def discount(price):
        return price * (1 - percent / 100)
    return discount

def add_tax(percent):
    def tax(price):
        return price * (1 + percent / 100)
    return tax

def round_price(price):
    return round(price, 2)

# Pipeline: валидация → скидка 20% → налог 10% → округление
calculate_price = pipe(
    validate_positive,
    apply_discount(20),
    add_tax(10),
    round_price
)

print(calculate_price(100))  # 88.0
# 100 → проверка → 80 → 88 → 88.0

Декораторы — это тоже композиция

def uppercase_decorator(func):
    def wrapper(*args, **kwargs):
        return func(*args, **kwargs).upper()
    return wrapper

def exclaim_decorator(func):
    def wrapper(*args, **kwargs):
        return f"{func(*args, **kwargs)}!!!"
    return wrapper

@exclaim_decorator
@uppercase_decorator
def greet(name):
    return f"hello, {name}"

print(greet("Alice"))  # "HELLO, ALICE!!!"
# greet → uppercase → exclaim

Стек декораторов читается снизу вверх: сначала uppercase_decorator, потом exclaim_decorator.


Частые ошибки

Ошибка 1: Неправильный порядок аргументов

def add_10(x):
    return x + 10

def multiply_2(x):
    return x * 2

# compose читается СПРАВА НАЛЕВО — multiply_2 выполнится первой!
wrong = compose(add_10, multiply_2)
print(wrong(5))  # 20  (5*2=10, 10+10=20)

# pipe читается СЛЕВА НАПРАВО — add_10 выполнится первой
right = pipe(add_10, multiply_2)
print(right(5))  # 30  ((5+10)*2=30)

Ошибка 2: Несовместимые сигнатуры функций

def add(a, b):    # принимает 2 аргумента
    return a + b

def square(x):    # принимает 1 аргумент
    return x ** 2

# ❌ ОШИБКА: square получит кортеж вместо числа
# pipeline = pipe(add, square)

# ✅ ПРАВИЛЬНО: зафиксировать один аргумент через partial
from functools import partial

add_10 = partial(add, 10)
pipeline = pipe(add_10, square)
print(pipeline(5))  # 225  ((5+10)^2)

Композиция функций — основа функционального стиля в Python. Используйте pipe() для читаемых цепочек преобразований и compose() когда важен математический порядок.

Ваша реакция на статью

💬 Комментарии (0)

🔐 Войдите в систему, чтобы оставить комментарий
🚪 Войти
💭

Комментариев пока нет

Станьте первым, кто поделится мнением об этой статье!

🔗 Похожие

Похожие статьи

Продолжите изучение с этими материалами

📝

Как функции работают вместе в Python 🧩

Небольшая функция обычно решает одну понятную задачу. Но настоящая программа состоит из нескольких задач: получить...

📅 09.08.2026 👁️ 78
📝

map() — Преобразуй каждый элемент!

Функция map() лениво применяет преобразование к каждому элементу итерируемого объекта.

📅 03.04.2026 👁️ 429
📝

filter() — Отбери нужное!

Функция filter() оставляет элементы, для которых проверка возвращает истинное значение.

📅 03.04.2026 👁️ 429
🎓 Продолжить обучение

В каких курсах используется этот материал

Перейдите к курсу, чтобы закрепить материал на практике.

Python с нуля: 7 практических проектов Открыть программу курса API на практике: взаимодействие с любыми сервисами Открыть программу курса