Декораторы и рекурсивные функции

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

Декораторы

Декораторы в Python — это функции, которые позволяют изменять или расширять функциональность других функций или методов. Они часто используются для добавления дополнительного поведения к функциям, не изменяя их код.

Основы декораторов

Декоратор — это функция, которая принимает другую функцию как аргумент и возвращает новую функцию, которая обычно добавляет что-то к оригинальной функции.

def my_decorator(func):
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("Hello!")

say_hello()

Вывод:

Something is happening before the function is called.
Hello!
Something is happening after the function is called.

В этом примере @my_decorator является синтаксическим сахаром для записи say_hello = my_decorator(say_hello).

Декораторы с аргументами

Декораторы могут принимать аргументы. Для этого создайте дополнительную функцию, которая будет принимать аргументы декоратора.

def repeat(num_times):
    def decorator_repeat(func):
        def wrapper(*args, **kwargs):
            for _ in range(num_times):
                func(*args, **kwargs)
        return wrapper
    return decorator_repeat

@repeat(num_times=3)
def greet(name):
    print(f"Hello, {name}!")

greet("Alice")

Вывод:

Hello, Alice!
Hello, Alice!
Hello, Alice!

Декораторы для методов класса

Декораторы также могут использоваться для методов класса. Один из распространенных декораторов для методов класса — @staticmethod и @classmethod.

class MyClass:
    @staticmethod
    def static_method():
        print("This is a static method.")

    @classmethod
    def class_method(cls):
        print(f"This is a class method. cls={cls}")

MyClass.static_method()
MyClass.class_method()

Вывод:

This is a static method.
This is a class method. cls=<class '__main__.MyClass'>

Рекурсивные функции

Рекурсивные функции — это функции, которые вызывают сами себя. Они полезны для решения задач, которые можно разделить на подзадачи того же типа, таких как задачи по типу "разделяй и властвуй".

Основы рекурсии

Рекурсивная функция должна иметь два основных компонента:

  1. Базовый случай: условие, при котором функция прекращает рекурсию.

  2. Рекурсивный случай: условие, при котором функция вызывает саму себя с новыми аргументами.

def factorial(n):
    if n == 0:
        return 1
    else:
        return n * factorial(n - 1)

print(factorial(5))  # Вывод: 120

Рекурсия для решения задач

Рекурсия часто используется для решения задач, таких как обход деревьев, поиск в графах, и другие задачи, которые могут быть выражены в виде меньших подзадач.

Пример: Фибоначчи

Числа Фибоначчи — это последовательность, где каждое число является суммой двух предыдущих чисел.

def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(6))  # Вывод: 8

Пример: Поиск в дереве

Рекурсия может использоваться для обхода деревьев.

class Node:
    def __init__(self, value):
        self.value = value
        self.children = []

def print_tree(node, level=0):
    print(' ' * level * 2 + str(node.value))
    for child in node.children:
        print_tree(child, level + 1)

# Пример дерева
root = Node(1)
root.children.append(Node(2))
root.children.append(Node(3))
root.children[0].children.append(Node(4))
root.children[0].children.append(Node(5))
root.children[1].children.append(Node(6))

print_tree(root)

Вывод:

1
  2
    4
    5
  3
    6

Оптимизация рекурсии

Рекурсия может быть неэффективной из-за повторных вычислений и может привести к переполнению стека вызовов. Для оптимизации рекурсии используются техники такие как мемоизация и декоративное кеширование.

Пример: Мемоизация

from functools import lru_cache

@lru_cache(maxsize=None)  # Кеширование результатов
def fibonacci(n):
    if n <= 1:
        return n
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

print(fibonacci(50))  # Быстрое вычисление за счет кеширования

Заключение

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

Last updated