python装饰器和包装器

时间:2016-04-14 05:12:52

标签: python function class decorator

我很难抓住装饰器,我最初认为装饰器是语法糖来做一个操作,如:

def decorator(x):
    return x*2

@decorator
def plusone(x):
    return x+1

print plusone(5)
# would print twelve, because: decorator(plusone(5)) as I have seen 
# in some tutorials

但我注意到首先需要在装饰器中创建包装函数。

为什么我们需要返回一个函数,而不是一个整数?

1 个答案:

答案 0 :(得分:3)

(Python)装饰器是修改函数的函数的语法糖,导致后者函数就像自身的修改版本一样。

让我们从一个简单(并不是那么好)的例子开始。说我们写

def double_me(f):
    return lambda x: 2 * f(x)

它接受一个带一个参数的函数,并返回一个带有一个参数的函数,并返回原始函数返回的double。然后我们可以像这样使用它:

def double_the_add_one(x):
    return x + 1
double_the_add_one = double_me(double_the_add_one)

>>> double_the_add_one(1)
4

请注意,我们首先定义double_the_add_one,然后修改double_the_add_one并将其绑定回double_the_add_one。所以现在它只是它自身的一个修改版本 - 它完成了原来的工作,然后只是将结果加倍。装饰者只是简单地说明了这一点:

@double_me 
def double_the_add_one(x):
    return x + 1

>>> double_the_add_one(1)
4

请注意,上面的装饰者并不是那么好:

  1. 它假设有一个位置参数。

  2. 它假设没有关键字参数。

  3. 如果装饰的函数有文档字符串,则会被破坏。

  4. 你应该使用functools.wraps来实际编写装饰器,使用那里的文档中的例子。