没有包装器的装饰器与函数 - Python

Decorator vs Function without wrapper - Python

我目前正在尝试了解装饰器是什么以及它们的用途。到现在为止,我了解到它们只是将 return 函数作为参数传递的函数,它们的目的是修改函数 w/o 修改原始函数。

我的问题与用于定义它们的经典结构有关。通常你会定义一个装饰器函数,并在其中定义另一个名为 wrapper 的函数,它 return 由装饰器函数编辑。

所以我的问题是,为什么只用一个函数就可以完成包装器,为什么要在装饰器内部创建包装器?这样做会不会更 "pythonic" 减少代码量?

例如下面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()

输出:

我最喜欢的国家的名字是:

瑞典

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

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

fav()

输出: 我最喜欢的国家的名字是:

瑞典

你说得对,装饰器就是一个以函数作为参数并返回函数的函数。但是这两个:

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 改变修饰函数的行为时,您将看到该消息三次。

在您的情况下,不需要包装函数。您没有对传递的参数和 return 参数执行任何操作。

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)

所以当修改传递的参数时,你必须使用包装器来实现。