装饰执行?

Decorator execution?

玩装饰器,发现一些奇怪的东西:我有一些简单的东西如下(装饰器将函数注册到列表:

stored_f = []

def register(f):
    stored_f.append(f.__name__)
    return f

@register
def say_hello(name):
    print(f"Hello {name}")

@register
def ur_awesome(name):
    return f"{name}, you are awesome!"

我认为上面的代码什么都不做(它什么也不会打印出来),因为我没有执行任何东西,但实际上一个打印命令“print(stored_f)”会有一个输出:

['say_hello', 'ur_awesome']

意味着 register() 中的行“stored_f.append(f.__name__)”实际上被执行了两次。这对我来说很奇怪。

我试着像往常一样在寄存器中定义一个 wrapper(),然后 return wrapper,问题就会消失。但是我仍然不明白为什么上面的代码会在不调用它的情况下部分执行装饰器。

导入和 运行 一个 Python 文件执行它并添加装饰器 @register 执行装饰器。

因此,即使您的脚本仅包含变量声明、装饰器和两个函数定义,当您 运行 它时,这些定义(定义函数)和装饰器函数都将被执行将被执行,以便函数被正确装饰。

在您的评论后添加:考虑一下:

stored_f = []

def register(f):
    stored_f.append(f.__name__)
    print('it runs!')
    return f

@register
def say_hello(name):
    print(f"Hello {name}")

@register
def ur_awesome(name):
    return f"{name}, you are awesome!"

你会发现,如果你运行这个脚本,输出是:

it runs!
it runs!

装饰器中的所有代码 运行s 而你只是 return 它收到的相同功能,所以 f 前后的工作方式相同。

此外,如果您将 say_hello("john") 添加到该脚本的末尾,您会发现装饰器不会再次 运行,只有函数 运行 再次出现。

此外,比较一下:

stored_f = []

def register(f):
    stored_f.append(f.__name__)
    def decorated_f(*args):
        print('it runs!')
        f(*args)
    return decorated_f

@register
def say_hello(name):
    print(f"Hello {name}")

say_hello("john")
say_hello("pete")

这导致:

it runs!
Hello john
it runs!
Hello pete

也许这更接近您的预期。请注意,装饰器不是 return 原始函数,它 return 是新函数。

根据 Grimar 的回答,我做了以下操作,至少可以从另一个角度解释一下,至少对我自己来说:

def do_twice(f):
    print('This will be executed anyway')
    def wrapper():
        f()
        f()
    return wrapper

@do_twice
def say_hello():
    print('This is say hello')

输出:

This will be executed anyway

如果我运行:

say_hello()

输出:

This is say hello
This is say hello