为什么python装饰器的结果是这样的..?

时间:2018-10-20 04:26:07

标签: python python-decorators

这些天,我学习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 个答案:

答案 0 :(得分:0)

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

@my_decorator
def say_hello():

它在幕后的实际作用是:

say_hello = my_decorator(say_hello)

因此,如果您这样做:

ret = my_decorator(say_hello)

您实际上要两次调用装饰器,因此您会看到两次消息。

答案 1 :(得分:0)

您已两次装饰函数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正在存储从wrapper返回的功能对象outer。但是,使用@decorator语法糖会自动执行第一个调用,即outer(stuff)。因此,以上示例可与以下示例进行比较:

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

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

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

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