Декораторы в Python

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

Вот их синтаксис:

@decorator
def function():
    pass

Здесь decorator – это функция, которая, так сказать, оборачивает другую функцию. То есть vape online в качестве аргумента она принимает исходную функцию и возвращает уже обновленную функцию, которая может содержать дополнительную логику.

Вот пример простого декоратора, который добавляет логирование к функции:

def log_decorator(func):
    def wrapper(*args, **kwargs):
        print(f"Вызов функции {func.__name__} с аргументами {args}, {kwargs}")
        result = func(*args, **kwargs)
        print(f"Результат выполнения функции: {result}")
        return result
    return wrapper

@log_decorator
def add_numbers(a, b):
    return a + b

В этом примере мы определили декоратор log_decorator, который принимает функцию func в качестве аргумента. Внутри декоратора мы определяем новую функцию wrapper, которая вызывает исходную функцию func, добавляя логирование до и после ее выполнения. Затем в качестве результата декоратора мы возвращаем wrapper.

Мы применили декоратор к функции add_numbers, используя синтаксис @log_decorator. Когда мы вызываем add_numbers(2, 3), декоратор log_decorator вызывается автоматически, добавляя логирование к функции add_numbers. Результат выполнения функции выводится на экран вместе с информацией о ее аргументах.

Конкретные примеры использования декораторов

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

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

Вот пример декоратора аутентификации:

def authenticate(func):
    def wrapper(request, *args, **kwargs):
        if request.user.is_authenticated:
            return func(request, *args, **kwargs)
        else:
            return HttpResponse("You must be logged in to access this page.")
    return wrapper

В этом примере мы определили декоратор authenticate, который принимает функцию func в качестве аргумента. Декоратор определяет новую функцию wrapper, которая проверяет, аутентифицирован ли пользователь, используя объект запроса Django request. Если пользователь аутентифицирован, то функция вызывается с переданными аргументами и возвращает результат. Если пользователь не аутентифицирован, функция не вызывается, и wrapper возвращает сообщение об ошибке.

Чтобы применить декоратор к функции, мы, как обычно, будем использовать синтаксис @authenticate:

@authenticate
def my_view(request):
    # Code for authenticated users only

Здесь мы определили функцию my_view, которая должна быть доступна только аутентифицированным пользователям. Мы применили декоратор authenticate к функции my_view, чтобы проверять аутентификацию пользователя перед вызовом функции.

Еще один пример использования декоратора аутентификации – это ограничение доступа к API. Вот пример:

from django.http import JsonResponse

def authenticate_api(func):
    def wrapper(request, *args, **kwargs):
        if request.user.is_authenticated:
            return func(request, *args, **kwargs)
        else:
            return JsonResponse({"error": "Authentication required."}, status=401)
    return wrapper

@authenticate_api
def my_api_view(request):
    # Code for authenticated API users only

В этом примере мы определили функцию my_api_view, которая предоставляет доступ к API только аутентифицированным пользователям. Мы применили декоратор authenticate_api к функции my_api_view, чтобы проверять аутентификацию пользователя перед вызовом функции. Если пользователь не аутентифицирован, функция возвращает ошибку с кодом 401.

Декоратор кэширования

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

Вот пример декоратора, который реализует кэширование результатов выполнения функции:

def memoize(func):
    cache = {}

    def wrapper(*args):
        if args in cache:
            return cache[args]
        else:
            result = func(*args)
            cache[args] = result
            return result

    return wrapper

В этом примере мы определили декоратор memoize, который принимает функцию func в качестве аргумента. Декоратор определяет словарь cache для хранения результатов выполнения функции и определяет новую функцию wrapper, которая проверяет, сохранен ли результат выполнения функции с данными аргументами в этом словаре. Если результат найден, он возвращается из словаря cache. Если результат не найден, функция вызывает исходную функцию func, сохраняет результат в словарь cache, возвращая этот самый результат.

Чтобы применить декоратор к функции, мы опять используем привычный синтаксис @memoize:

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

В данном примере мы определили функцию factorial, которая вычисляет факториал числа. Мы применили декоратор memoize к функции factorial, чтобы кэшировать результаты выполнения функции и ускорить ее работу.

Другой пример применения декоратора кэширования – это кэширование результатов запросов к API. Вот пример:

import requests
import json

def memoize(func):
    cache = {}

    def wrapper(*args):
        if args in cache:
            return cache[args]
        else:
            result = func(*args)
            cache[args] = result
            return result

    return wrapper

@memoize
def get_data_from_api(endpoint):
    response = requests.get(endpoint)
    data = json.loads(response.text)
    return data

В этом примере мы определили функцию get_data_from_api, которая использует библиотеку requests для выполнения запросов к API и возвращает данные, полученные из API. Мы применили декоратор memoize к функции get_data_from_api, чтобы кэшировать результаты запросов и ускорить работу функции, если она вызывается несколько раз с одним и тем же аргументом endpoint.

Заключение

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

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Scroll to Top