装饰器如何标记功能?

时间:2015-03-21 17:43:16

标签: python flask decorator python-decorators

我正在阅读基本的Flask教程,其中包含以下代码:

from flask import Flask
app = Flask(__name__)

@app.route("/")
def hello():
    return "Hello World!"

if __name__ == "__main__":
    app.run()

此外,我还从许多网站(包括Stackoverflow Decorators

)了解了Python装饰器的基础知识

我假设在前面的代码中,函数hello将被更改和修饰,并且为了运行应用程序,我需要在某处调用函数hello()。 Flask如何确定它必须调用的函数的名称。

只是用装饰器包装函数定义会以某种方式标记该函数吗?如果是这样,怎么样?

例如,在下面的代码中,我在某处的某个地方调用了我装饰的功能:

def decorate(foo):
    print("I'm doing a lot of important stuff right now")

    def inner():
        print("Some stuff 1")
        foo()
        print("Some stuff 2")

    return inner

@decorate
def hello():
    print("Hello")

hello()

3 个答案:

答案 0 :(得分:4)

decorate中,foo是您要装饰的功能(在本例中为hello)。您可以将函数存储在某个列表或字典中,因为它是一个普通对象。

例如:

decorated_functions = []

def decorate(foo):
    def inner():
        print("Some stuff 1")
        foo()
        print("Some stuff 2")

    decorated_functions.append(inner)
    return inner

@decorate
def hello():
    print("Hello")

## The above is the same as:
# def hello():
#     print("Hello")
# hello = decorate(hello)

print(decorated_functions[0] == hello) # prints True
decorated_functions[0]() # prints "Some stuff 1", "Hello", and "Some stuff 2"
hello() # same as above

答案 1 :(得分:1)

装饰器实际上是Python中非常简单的构造。以下两个例子是等效的:

@foo
def bar():
     pass

def bar():
     pass

bar = foo(bar)

因此,您在第一个示例中对hello的定义与此相当:

def hello():
     return "Hello World!"

hello = app.route("/")(hello)

双重函数调用可能有点令人困惑,所以让我们像这样重写:

_tempfn = app.route("/")
hello = _tempfn(hello)

所以现在应该很清楚app.route实际上并不是装饰器,它是创建装饰器的函数。现在不明显的是新装饰者做了什么。如果不查看Flash的来源,可能会将函数hello添加到app的字典成员中。所以app.route的实现方式如下:

class app(object):
    def route(self, path):
        def decorator(fn):
            self.pathmap[path] = fn
            return fn
        return decorator

请注意,这几乎是Jon Piparsky provided链接中给出的解释的精简版本。

答案 2 :(得分:1)

装饰器只是在查找表中注册该函数。装饰者不需要以任何方式修改函数,装饰者可以做很多其他有用的事情。

实际上,python中的装饰器

@some_decorator
def foo():
    pass

只是

的简短形式
def foo():
    pass

foo = some_decorator(foo)

并且函数some_decorator可以对其参数执行任何操作,并且可以返回任何返回值,但通常会返回一个函数。