【问题标题】:why python decorator result like this..? [closed]为什么 python 装饰器的结果是这样的..? [关闭]
【发布时间】:2019-03-24 22:32:20
【问题描述】:

这几天在研究python装饰器,我的问题代码是这样的。

import functools
def my_decorator(func):
    @functools.wraps(func)
    def wrapper():
        print("Something is happening before the function is called.")
        func()
        print("Something is happening after the function is called.")
    return wrapper

@my_decorator
def say_hello():
    print("hello!")

ret = my_decorator(say_hello)
ret()

其实,我期待这个结果

Something is happening before the function is called.
hello!
Something is happening after the function is called.

但真正的输出是这样的。

Something is happening before the function is called.
Something is happening before the function is called.
hello!
Something is happening after the function is called.
Something is happening after the function is called.

谁能告诉我为什么会出现这样的结果?

【问题讨论】:

  • 因为你使用了 2 次装饰器,第一次使用 @my_decorator,第二次使用:my_decorator(say_hello)
  • 这个问题应该作为一个错字关闭,它对 OP 的其他人没有帮助,尤其是这种点击诱饵标题

标签: python python-decorators


【解决方案1】:

你已经装饰了你的函数say_hello 两次。

通常,在装饰器的示例中,函数包装器被显式调用,即:

def outer(f):
  def wrapper():
     f()
  return wrapper

def stuff():
  print('hello from stuff')

new_stuff = outer(stuff)
new_stuff()

这会将'hello from stuff' 输出到控制台,因为new_stuff 正在存储从outer 返回的函数对象wrapper。但是,使用@decorator 语法糖会自动执行第一次调用,即outer(stuff)。因此,上面的例子相当于:

def outer(f):
  def wrapper():
    f()
  return wrapper

@outer
def stuff():
  print('hello from stuff')

因此,在您的示例中,只需调用 say_hello (say_hello()) 即可正确输出

Something is happening before the function is called.
hello!
Something is happening after the function is called.

【讨论】:

    【解决方案2】:

    当你应用这样的装饰器时:

    @my_decorator
    def say_hello():
    

    它实际上在幕后所做的是:

    say_hello = my_decorator(say_hello)
    

    如果你这样做:

    ret = my_decorator(say_hello)
    

    您实际上调用了两次装饰器,因此您看到的结果是双重消息。

    【讨论】:

      猜你喜欢
      • 2016-11-25
      • 1970-01-01
      • 2020-03-31
      • 2010-10-03
      • 2019-12-11
      • 2014-04-09
      • 2021-05-10
      • 2010-09-17
      • 1970-01-01
      相关资源
      最近更新 更多