【问题标题】:python decorators and wrapperspython 装饰器和包装器
【发布时间】:2016-04-14 05:12:52
【问题描述】:

我很难掌握装饰器,我最初认为装饰器是语法糖,可以执行以下操作:

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

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

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

【问题讨论】:

  • 因为装饰器就是这样做的:他们接受一个函数并返回一个新函数。您是否阅读过the documentation 和/或搜索过关于 Python 装饰器的无数解释?
  • 你的装饰器本质上使它成为一个新函数(接受相同的参数)。装饰器本身不会调用(评估)您的函数,因为它不知道参数。如果你想在装饰器中返回x() * 2x() 的参数是什么?
  • @brenbarn 是的,我有,这就是我作为最后手段来到这里的原因。希望你们中的一个人能解释得更清楚一点。
  • @vjgaero:那么也许你应该解释为什么你认为装饰器的行为与你在这个问题中的建议一样。你读到了什么让你有这样的印象?
  • @brenBarn 因为我读过装饰器教程。一些导师解释说装饰器“差不多”就像我上面解释的那样。

标签: python function class decorator


【解决方案1】:

(Python) 装饰器是函数修改函数的语法糖,使函数的行为类似于自身的修改版本。

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

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

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

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. 如果修饰函数有一个文档字符串,它就会被破坏。

您可能应该使用functools.wraps 来使用那里的文档中的示例实际编写装饰器。

【讨论】:

    猜你喜欢
    • 2021-05-20
    • 1970-01-01
    • 2018-03-07
    • 1970-01-01
    • 1970-01-01
    • 2015-10-09
    • 1970-01-01
    • 2012-12-25
    • 2014-02-16
    相关资源
    最近更新 更多