Декоратор против функции без оболочки - Python - PullRequest
0 голосов
/ 03 марта 2020

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

Мой вопрос связан с classi c структура используется для их определения. Обычно вы определяете функцию декоратора, а внутри нее - другую функцию, называемую оберткой, которая возвращается функцией декоратора.

Итак, мой вопрос: почему обертка создается внутри декоратора, когда это можно сделать только с помощью функции? Разве не было бы более "pythoni c", чтобы уменьшить сторону кода, делая так?

Например, следующие 2 фрагмента кода:

def country(func):
    def wrapper_function():
        print("The name of my favorite country is: ")
        return func()
    return wrapper_function

@country # == fav_country = country(fav)
def fav():
    print("Sweden")

fav()

OUTPUT :

Имя моей любимой страны:

Швеция

def country(func):
    print("The name of my favorite country is: ")
    return func

@country # == fav_country = country(fav)
def fav():
    print("Sweden")

fav()

ВЫХОД: Название моей любимой страны:

Швеция

Ответы [ 2 ]

3 голосов
/ 03 марта 2020

Вы правы, что декоратор - это не что иное, как функция, принимающая функцию в качестве аргумента и возвращающая функцию. Но эти два:

def country1(func):
    def wrapper_function():
        print("The name of my favorite country is: ")
        return func()
    return wrapper_function

def country2(func):
    print("The name of my favorite country is: ")
    return func

не эквивалентны. Рассмотрим

@country1
def fav1():
    print("Sweden")

@country2
def fav2():
    print("Sweden")

и посмотрим, что произойдет при вызове

fav1()
fav1()
fav1()

и

fav2()
fav2()
fav2()

Ваш country2 не изменяет исходную функцию и результат The name of my favorite country is: печатается только один раз в процессе оформления (при объявлении функции). Пока country1 меняет поведение оформленной функции, вы увидите сообщение три раза.

0 голосов
/ 03 марта 2020

В вашем случае функция-обертка не нужна. Вы ничего не делаете с переданными параметрами и возвращаемыми параметрами.

def printall(func):
    def inner(*args):
        print('Arguments for args: {}'.format(args))
        return func(*args)
    return inner

@printall
def random_func(*args):
    return sum(*args)

a = random_func(2, 2)

Это полезно, например, если вы хотите, чтобы переданные параметры начинались с более высокого значения (вроде как добавленное смещение). Тогда вы можете сделать:

def offset(func):
    def inner(*args):
        args = [arg + 2 for arg in args]
        return func(*args) # <-- here it is calling your random_func with modified passed parameters!
    return inner

@offset
def random_func(*args):
    return sum(*args)

a = random_func(2, 2)

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

...