为什么装饰器功能不简单?

时间:2017-04-28 01:57:25

标签: python

为什么装饰器函数需要定义自己的函数而不是仅仅运行代码......所以不要这样:

def decor(func):
    def wrap():
        print("============")
        func()
        print("============")
    return wrap

def print_text():
    print("Hello world!")

decorated = decor(print_text)
decorated()

为什么不这样:

def decor(func):
    print("============")
    func()
    print("============")

def print_text():
    print("Hello world!")

decorated = decor(print_text)
decorated

2 个答案:

答案 0 :(得分:3)

装饰器语法的目的是将函数应用于可调用函数,并生成另一个可调用。在你的第二个例子中,你没有真正的装饰者;您只是将函数引用传递给另一个调用它的函数。

换句话说,与装饰器语法一起使用的函数的定义特征是它返回另一个函数。装饰器语法没有什么特别之处;它是语法糖,并且它没有任何,你无法用常规Python语法完成。以下

@foo
def bar(...):
    ...

完全相同,但更简洁,更明确的形式

def bar(...):
    ...

bar = foo(bar)

答案 1 :(得分:1)

每次评估时,您的第二个代码块都可以“完成工作”。如果你需要多次这样做怎么办?每次必须评估表达式decor(some_function)时,即使装饰函数some_function恰好是同一个东西。如果评估的背景不完全在您的控制范围内会怎样?

使用第一种方法,您基本上将装饰函数包装在可以在以后评估的相同thunk中。你可以在每次需要它时调用相同的thunk。您甚至可以将呼叫委托给其他人。

你的装饰师例子很简单。当代码变得更复杂时,Python将函数作为第一类对象返回的能力是一个福音。一个例子是API需要回调:

def frob(some, args, callback=your_function):

现在,您已经编写了回调函数,并发现memoization可以提升性能。使用装饰器模式,您可以执行类似

的操作
my_function_memoized = memoize(my_function, *even_more_parameters_controlling_the_memoization_behavior)  # returns decorate function
... ...
frob(some, args, callback=my_function_memoized)

也就是说,装饰的thunk只能在my_function的位置使用。这在Python中发生了很多,因为Python使得传递callables非常容易。