使用装饰器和显式调用有什么区别?

4

假设我们有一个装饰器:

def decor(function):
    def result():
        printf('decorated')
        return function()
    return result

以下代码有何区别?
@decor
def my_foo():
    print('my_foo')

并且:

def my_foo():
    print('my_foo')
my_foo = decor(my_foo)
3个回答

8

你的最后一段代码几乎是装饰器的定义。唯一的区别在于,在第一种情况下,名称 decor 在函数定义之前被计算,而在第二种情况下,在函数定义之后被计算。只有当执行函数定义更改名称所指向的内容时,才会产生差异。

无意义的示例:

def decor(function):
    def result():
        printf('decorated')
        return function()
    return result

def plonk():
    global decor
    decor = lambda x: x
    return None

现在
@decor
def my_foo(foo=plonk()):
    print('my_foo')

不同于

def my_foo(foo=plonk()):
    print('my_foo')
my_foo = decor(my_foo)

非常感谢您的解释。这个例子确实很酷;-) - gruszczy
抱歉,但是有人可以详细解释一下这个答案吗?似乎有一些见解,但我不明白...也许只有10k+的声望才能理解..?! - aerin
1
@ToussaintLouverture 原始问题询问了两个代码片段在语义上的差异,因此这个答案努力寻找这两个代码片段实际上不同的情况。由于在实践中代码片段是相同的,这需要一些荒谬的代码:您需要编写一个函数_定义_,它通过副作用更改全局名称。没有正常人会编写这样的代码,但这是一个有趣的例子。 - Sven Marnach

4

没有区别。 @decorator 语法只是让人更容易理解正在应用装饰器。 (这是语法糖的一个例子。)


1

如果有区别,那就是 Python 2.4 以前的版本不支持 @decorator 语法,而显式调用装饰器则已经支持自石器时代以来。此外,@decorator 语法必须应用于函数定义,并且必须使用相同的函数名称,而显式调用装饰器可以稍后应用,并且可以重命名被装饰的函数。

除非您有非常、非常、非常好的理由不这样做,否则请使用@decorator 语法;这几乎从来没有。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接