首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python Decorator自燃

Python Decorator自燃
EN

Stack Overflow用户
提问于 2013-09-30 20:11:42
回答 2查看 639关注 0票数 0

我对Python相当陌生,并且一直在学习装饰师。在使用了Flask之后,我试图编写一些代码来模拟它们的路由处理程序/装饰器,只是为了了解装饰器(带有参数)是如何工作的。

在下面的代码中,当脚本运行时,路由修饰器似乎会调用自己。我的问题是,当我运行这个脚本时,app.route()怎么可能被调用,这里到底发生了什么?注意,我没有在任何地方直接调用我的index()函数。

代码语言:javascript
复制
# test.py

class Flask(object):

    def __init__(self, name):
        self.scriptname = name

    def route(self, *rargs, **kargs):
        args = list(rargs)
        if kargs:
            print(kargs['methods'])
        def decorator(f):
            f(args[0])
        return decorator

app = Flask(__name__)

@app.route("/", methods = ["GET","PUT"])
def index(rt):
    print('route: ' + rt)

上面在我的终端上打印了这个:

代码语言:javascript
复制
$ python test.py
['GET', 'PUT']
route: /

任何洞察力都将不胜感激。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-09-30 20:30:25

@app.route("/", methods = ["GET","PUT"])是一个可执行语句:它调用app对象的route()方法。因为它位于模块级别,所以在导入脚本时将执行它。

现在,调用app.route(...)的结果是一个函数,因为您已经使用@将其标记为一个装饰符,因此该函数将包装index。请注意,语法只是这方面的一个快捷方式:

代码语言:javascript
复制
index = app.route(...)(index)

换句话说,Python将调用app.route()index作为参数返回的函数,并将结果存储为新的index函数。

然而,你在这里错过了一个层次。一个普通的装潢师,没有平面语,是这样写的:

代码语言:javascript
复制
@foo
def bar()
   pass

在导入模块时,运行foo()并返回一个包装bar的函数。但是在装饰器调用中调用您的route()函数!因此,实际上您的函数需要返回一个装饰函数,该函数本身返回一个包装原始函数的函数.当然是挠头了。

您的route方法应该更像这样:

代码语言:javascript
复制
def route(self, *rargs, **kargs):
    args = list(rargs)
    if kargs:
        print(kargs['methods'])
    def decorator(f):
        def wrapped(index_args):
            f(args[0])
        return wrapped
    return decorator
票数 2
EN

Stack Overflow用户

发布于 2013-09-30 20:18:58

基本上..。app.route(index, "/", ["GET", "PUT"])是一个函数。这是要调用的函数,而不是索引。

在代码中,当调用index()时,它调用app.route(index, "/", ["GET", "PUT"])。首先打印kargs['methods'],然后创建装饰器函数:

代码语言:javascript
复制
def decorator(f):
    f(args[0])

这个装饰器将用一个参数args[0]调用修饰函数(args[0]),这里的参数是"/“。这个打印route: /

我发现的装饰师最好的解释是:How to make a chain of function decorators?

如果你不想自燃,你可以用这样的方式定义你的装饰者:

代码语言:javascript
复制
def route(*rargs, **kargs):
    args = list(rargs)
    if kargs:
        print(kargs['methods'])
    def decorator(f):
        f(args[0])
    return decorator

@app.route("/", methods = ["GET","PUT"])
def index(rt):
    print('route: ' + rt)

但是,索引的rt参数将永远不会被使用,因为route总是用args[0]调用index,而args[0]总是\.

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19102930

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档