【问题标题】:Python dynamic decorators - why so many wraps?Python 动态装饰器 - 为什么有这么多包装?
【发布时间】:2011-08-11 12:25:10
【问题描述】:

所以我对 Python 装饰器还是个新手——我以前用过它们,但我从来没有自己做过。我正在阅读this tutorial(那个特定的段落),我似乎不明白为什么我们需要三个级别的函数?为什么我们不能这样做:

def decorator(func, *args, **kwargs):
    return func(*args,**kwargs)

谢谢:)

【问题讨论】:

    标签: python decorator


    【解决方案1】:

    装饰器通过添加包装器来修改函数。在你装饰函数的时候,它还没有被调用,所以你没有任何参数(或关键字参数)可以查看。你现在所能做的就是创建一个新函数,当它最终获得这些参数时将处理它们。

    【讨论】:

      【解决方案2】:

      那么,如果你在一个函数上调用那个装饰器会发生什么?

      @decorator
      def foo(): pass
      

      这段代码会立即调用 foo,这是我们不想要的。装饰器被调用,它们的返回值替换了函数。和说的一样

      def foo(): pass
      foo = decorator(foo)
      

      因此,如果我们有一个调用 foo 的装饰器,我们可能希望有一个函数返回一个调用 foo 的函数——它返回的函数将替换 foo。

      def decorator(f):
          def g(*args, **kwargs):
              return f(*args, **kwargs)
          return g
      

      现在,如果我们想将选项传递给装饰器,我们不能像您的示例中那样将它们与函数完全并行传递。它没有语法。所以我们定义了一个返回参数化装饰器的函数。它返回的装饰器将是一个闭包。

      def argument_decorator(will_I_call_f):
          def decorator(f):
              def g(*args, **kwargs):
                  if will_I_call_f: return f(*args, **kwargs)
              return g
          return decorator
      

      所以我们可以做

      decorator = argument_decorator(True)
      @decorator
      def foo(): pass
      

      Python 提供了方便的语法,您可以在其中内联函数调用:

      @argument_decorator(True)
      def foo(): pass
      

      所有这些都是非装饰器语法的语法糖

      def foo(): pass
      foo = argument_decorator(True)(foo)
      

      【讨论】:

      • +1 很好的解释。最后一个“在行动”的例子也很有用,恕我直言。
      • 当你想为你的装饰器提供参数时,初始化/调用模式是另一种选择。 artima.com/weblogs/viewpost.jsp?thread=240845
      • 谢谢,这真的很有帮助:)
      • 就我个人而言,除非我想维护装饰器的状态,否则我不会使用装饰器类。当你习惯闭包时,它们是可读的。不幸的是,提问者不是。 :(
      • @detly:装饰器类在应用于方法时会引起麻烦 - 因为它们不是函数,所以包装它们的对象不会被识别为方法。您必须复制 instancemethod 描述符的逻辑(按照 Python 标准,这是比较多的样板代码,而且并不明显),否则 self 将不会被传入。
      猜你喜欢
      • 2021-05-10
      • 1970-01-01
      • 2012-01-09
      • 2020-06-29
      • 2018-03-27
      • 2016-11-25
      • 2020-07-24
      • 1970-01-01
      • 2018-11-20
      相关资源
      最近更新 更多