Введение:

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

Создание заклинаний… Упс, я имею в виду декораторов!

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

def wand_of_uppercase(function):
    def wrapper():
        result = function()
        return result.upper()
    return wrapper

@wand_of_uppercase
def say_abracadabra():
    return "abracadabra!"

print(say_abracadabra())  # Output: ABRACADABRA!

Объяснение. В этом примере мы определяем декоратор с именем `wand_of_uppercase`. Он принимает функцию в качестве аргумента и возвращает новую функцию под названием «обертка». Функция «обертка» оборачивает исходную функцию и выполняет некоторые дополнительные действия. В этом случае он преобразует результат исходной функции в верхний регистр. Затем мы применяем декоратор к функции `say_abracadabra`, используя синтаксис `@`. Когда мы вызываем `say_abracadabra()`, она вызывает декорированную версию функции, в результате чего появляется строка «abracadabra!» трансформируется в «АБРАКАДАБРА!».

Продвинутые чары: декораторы с изюминкой

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

def wand_of_repetition(times):
    def decorator(function):
        def wrapper(*args, **kwargs):
            for _ in range(times):
                result = function(*args, **kwargs)
            return result
        return wrapper
    return decorator

@wand_of_repetition(3)
def say_pocus(name):
    print(f"Pocus, pocus, {name}!")

say_pocus("Harry")  # Output: Pocus, pocus, Harry! (printed 3 times)

Объяснение. В этом примере мы определяем декоратор с именем `wand_of_repetition`, который принимает аргумент `times`. Сам декоратор возвращает другую функцию декоратора, называемую `decorator`. Функция «декоратор» принимает исходную функцию в качестве аргумента и возвращает функцию «обертки». Функция `wrapper` принимает любое количество позиционных и ключевых аргументов, используя `*args` и `**kwargs` соответственно. Затем он повторяет выполнение исходной функции `times` несколько раз. Во фрагменте кода мы применяем декоратор `wand_of_repetition` к функции `say_pocus` с помощью `@wand_of_repetition(3)`. Когда мы вызываем `say_pocus("Harry")`, он печатает "Pocus, pocus, Harry!" три раза.

Волшебство вне функций: декораторы классов

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

def spell_of_extra_property(cls):
    cls.new_property = "extra power"
    return cls

@spell_of_extra_property
class Wizard:
    pass

print(Wizard.new_property)  # Output: extra power

Объяснение. В этом примере мы определяем декоратор под названием `spell_of_extra_property`, который принимает класс в качестве аргумента. В декораторе мы добавляем в класс новый атрибут с именем `new_property`. Декоратор возвращает измененный класс. Применяя декоратор spell_of_extra_property к классу Wizard с помощью @spell_of_extra_property, мы добавляем в класс атрибут new_property. Когда мы обращаемся к `Wizard.new_property`, он возвращает «дополнительную мощность».

Окончательное колдовство: связывание и вложение декораторов

Приготовьтесь стать свидетелем самого завораживающего трюка: связывание и вложение декораторов! Мы раскроем секреты комбинирования нескольких декораторов для создания умопомрачительных эффектов. Приготовьтесь к поистине впечатляющему волшебству Python!

def wand_of_uppercase(function):
    def wrapper():
        result = function()
        return result.upper()
    return wrapper

def wand_of_repetition(times):
    def decorator(function):
        def wrapper():
            for _ in range(times):
                result = function()
            return result
        return wrapper
    return decorator

@wand_of_repetition(2)
@wand_of_uppercase
def say_bibbidi():
    return "bibbidi, bobbidi, boo!"

print(say_bibbidi())  # Output: BIBBIDI, BOBBIDI, BOO! (printed twice)

Объяснение.В этом примере мы определяем два декоратора, `wand_of_uppercase` и `wand_of_repetition`. Декоратор wand_of_uppercase преобразует результат исходной функции в верхний регистр, а декоратор wand_of_repetition многократно повторяет выполнение функции. Затем мы применяем эти декораторы к функции `say_bibbidi`, используя синтаксис `@`, причем первым появляется `@wand_of_repetition(2)`. Когда мы вызываем `say_bibbidi()`, она вызывает декорированную версию функции. Сначала декоратор wand_of_repetition выполняет функцию дважды, а затем декоратор wand_of_uppercase преобразует результат в верхний регистр.

Волшебство в реальном мире: практические примеры использования и примеры

Хватит заклинаний, приступим к практической магии! Мы расскажем о реальных случаях использования, в которых декораторы могут творить чудеса. Мы покажем вам, как декораторы могут заставить ваш код сиять и сиять, от заклинаний регистрации до зелий синхронизации.

Теперь, когда вы освоили искусство декораторов, пришло время изучить их практическое применение. В этом разделе мы рассмотрим практические примеры использования, когда декораторы могут творить чудеса, заставляя ваш код сиять и сиять. Приготовьтесь раскрыть магию!

Регистрация заклинаний: добавление функции регистрации

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

def log_execution(func):
    def wrapper(*args, **kwargs):
        print(f"Executing function: {func.__name__}")
        result = func(*args, **kwargs)
        print(f"Function {func.__name__} executed successfully")
        return result
    return wrapper

@log_execution
def calculate_sum(a, b):
    return a + b

result = calculate_sum(5, 7)  # Output: Executing function: calculate_sum
                              #         Function calculate_sum executed successfully
print(result)  # Output: 12

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

Зелья времени: измерение времени выполнения

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

import time

def measure_time(func):
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        execution_time = end_time - start_time
        print(f"Function {func.__name__} executed in {execution_time} seconds")
        return result
    return wrapper

@measure_time
def calculate_factorial(n):
    if n == 0 or n == 1:
        return 1
    return n * calculate_factorial(n - 1)

result = calculate_factorial(5)  # Output: Function calculate_factorial executed in 2.384185791015625e-05 seconds
print(result)  # Output: 120

В этом примере мы создаем декоратор с именем Measure_time, который измеряет время выполнения функции. Применяя этот декоратор к функции calculate_factorial с помощью @measure_time, мы определяем время выполнения и печатаем результат. Это может быть полезно для профилирования кода и выявления узких мест в производительности.

Заклинания авторизации: контроль доступа и разрешения

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

def authorize(role):
    def decorator(func):
        def wrapper(*args, **kwargs):
            user_role = get_user_role()  # Assume this function retrieves the user's role
            if user_role == role:
                return func(*args, **kwargs)
            else:
                raise PermissionError("Access denied")
        return wrapper
    return decorator

@authorize(role="admin")
def delete_user(user_id):
    # Code to delete the user

delete_user(123)  # If the user has the "admin" role, the function will be executed

В этом примере мы определяем декоратор с именем authorize, который принимает аргумент роли. Сам декоратор возвращает другую функцию-декоратор, называемую декоратором, которая, в свою очередь, возвращает функцию-оболочку. Функция-оболочка выполняет проверку авторизации, сравнивая роль пользователя с указанным аргументом роли. Если роли совпадают, выполняется декорированная функция; в противном случае возникает PermissionError.

На страже ваших заклинаний: сохранение метаданных функций

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

Волшебный мир библиотек и фреймворков

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

Вывод:

Поздравляю, юный волшебник! Теперь вы раскрыли истинный потенциал декораторов. Вооружившись этими новообретенными знаниями, вы можете использовать силу декораторов, чтобы ваш код Python сиял ярче, чем тысяча заклинаний Lumos. Так что вперед, окунитесь в магию, и пусть ваши заклинания Python будут не чем иным, как экстраординарными!