【问题标题】:defining functions in decorator在装饰器中定义函数
【发布时间】:2009-07-18 03:14:08
【问题描述】:

为什么这不起作用?我怎样才能让它工作?也就是说,我怎样才能让 gu 在我的装饰函数中访问?

def decorate(f):
    def new_f():
        def gu():
            pass
        f()
    return new_f

@decorate
def fu():
    gu()

fu()

我是否需要以某种方式将 gu 添加到已定义函数的字典中?或者我可以在调用它之前将 gu 添加到 f 的本地命名空间吗?

【问题讨论】:

    标签: python aop decorator argument-passing


    【解决方案1】:

    如果您需要将gu 传递给fu,您需要通过参数显式执行此操作:

    def decorate(f):
        def new_f():
            def gu():
                pass
            f(gu)
        return new_f
    
    @decorate
    def fu(gu):
        gu()
    
    fu()
    

    【讨论】:

    • 有没有办法可以将函数 gu 添加到 f 的属性中,以尽量减少对 fu 实际定义的干扰。我的意思是,这是装饰器或 AOP 的目标;分离出问题。
    • @Alex 如果gu 是独立于fu 的概念,你为什么在fu 中调用它而不是new_f?如果它们真的是分开的,那么当它们彼此不可见时会更加方便。您能否在您的问题中提供更多细节以澄清?
    【解决方案2】:

    gunew_f 函数的本地函数,它是 decorate 函数的本地函数。

    【讨论】:

      【解决方案3】:

      gu() 仅在 new_f() 中定义。除非您将其返回或将其锚定到 new_f() 或其他内容,否则无法从 new_f() 外部引用它

      我不知道你在做什么,但这个方案似乎很复杂。也许你可以找到一个不太复杂的解决方案。

      【讨论】:

      • 这个例子毫无意义,但我试图给出最简单的例子来说明问题。我想做什么应该很清楚。我想在装饰器定义中定义一个函数,以便在装饰函数中使用。
      • @Alex:你能描述一下你试图解决的更高层次的问题吗?也许有人可以使用完全不同的方法提出更清洁的解决方案。
      【解决方案4】:

      原则上,您可以使用与旧代码相同的代码创建新函数,但用修改后的代码替换全局范围:

      import new
      
      def with_bar(func):
          def bar(x):
              return x + 1
          f_globals = func.func_globals.copy()
          f_globals['bar'] = bar
          return new.function(func.func_code, f_globals,
                              func.func_name, func.func_defaults, func.func_closure)
      
      @with_bar
      def foo(x):
          return bar(x)
      
      print foo(5) # prints 6
      

      在实践中,您确实应该找到一种更好的方法来做到这一点。将函数作为参数传递是一种选择。可能还有其他方法,但如果没有高级问题描述,很难判断哪种方法适合。

      【讨论】:

        【解决方案5】:

        为什么不让你的装饰器成为一个类而不是一个函数呢?这显然是可能的,正如我在查看 property 内置的帮助时发现的那样。 (以前,我认为你可以只将装饰器应用于类,而不是装饰器本身可以是类。)

        (当然,gu 必须是类或内部类的方法。)

        【讨论】:

          猜你喜欢
          • 2015-10-23
          • 1970-01-01
          • 2015-04-28
          • 2021-04-22
          • 2014-08-25
          • 1970-01-01
          • 2013-02-06
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多