简体   繁体   English

Python - 在 Decorator 之后调用预定义的 Function

[英]Python - Call Pre-defined Function after Decorator

I am building a straight-forward Flask API. After each decorator for the API endpoint, I have to define a function that simply calls another function I have in a separate file.我正在构建一个直接的 Flask API。在 API 端点的每个装饰器之后,我必须定义一个 function,它只是调用另一个 function 我在一个单独的文件中。 This works fine, but seems redundant.这工作正常,但似乎是多余的。 I would rather just call that pre-defined function directly, instead of having to wrap it within another function right after the decorator.我宁愿直接调用预定义的 function,而不必在装饰器之后将其包装在另一个 function 中。 Is this possible?这可能吗?

What I have currently:我目前拥有的:

import routes.Locations as Locations

# POST: /api/v1/locations
@app.route('/locations', methods=['GET'])
def LocationsRead ():
   return Locations.read()

Locations.read() function looks like this: Locations.read() function 看起来像这样:

def read():
   return {
      'id': 1,
      'name': 'READ'
   }

What I am hoping to do:我希望做什么:

import routes.Locations as Locations

# POST: /api/v1/locations
@app.route('/locations', methods=['GET'])
Locations.read()

The @ syntax of decorators is just syntactic sugar for:装饰器的@语法只是语法糖:

def LocationsRead():
   return Locations.read()

LocationsRead = app.route('/locations', methods=['GET'])(LocationsRead)

So you could do something like:所以你可以这样做:

LocationsRead = app.route('/locations', methods=['GET'])(Locations.read)

Arguably, that takes a bit longer to understand the intention and it's not that much more terse that your original code.可以说,理解意图需要更长的时间,而且它并不比您的原始代码简洁得多。

With exceptions and logging the stack trace, you also lose one level of the stack trace.除了异常和记录堆栈跟踪之外,您还会丢失一级堆栈跟踪。 That will make it hard to identify where and how Locations.read is being added as a route in a flask. The stack trace will jump straight from the flask library to routes.Locations:read .这将很难确定在 flask 中将Locations.read添加为路由的位置和方式。堆栈跟踪将从 flask 库直接跳转到routes.Locations:read If you want to know how route was configured (eg.what the URL is parameterised with or what methods it works with), then you'll have to know already know which file the "decoration" took place.如果你想知道路由是如何配置的(例如 URL 是用什么参数化的或者它使用什么方法),那么你必须已经知道“装饰”发生在哪个文件中。 If you use normal decoration, you'll get a line pointing at the file containing @app.route('/locations', methods=['GET']) .如果你使用普通装饰,你会得到一行指向包含@app.route('/locations', methods=['GET'])的文件。

That is, you get a debatable benefit and the potential to make debugging harder.也就是说,您获得了值得商榷的好处,并有可能使调试变得更加困难。 Stick with the @ decorator syntax.坚持使用@装饰器语法。

Thanks to @Dunes and @RodrigoRodrigues answers, I played around with it more and found that the following works both for endpoints with and without arguments to pass, like an ID.多亏了@Dunes 和@RodrigoRodrigues 的回答,我对它进行了更多研究,发现以下内容适用于有和没有 arguments 传递的端点,例如 ID。 See the code below.请参阅下面的代码。

# GET: /api/v1/locations
app.route(basepath + '/locations', methods=['GET'])(Locations.read)
# GET: /api/v1/locations/{id}
app.route(basepath + '/locations/<int:id>', methods=['GET'])(Locations.read)
# POST: /api/v1/locations
app.route(basepath + '/locations', methods=['POST'])(Locations.create)
# PUT: /api/v1/locations/{id}
app.route(basepath + '/locations/<int:id>', methods=['PUT'])(Locations.update)
# DELETE: /api/v1/locations/{id}
app.route(basepath + '/locations/<int:id>', methods=['DELETE'])(Locations.delete)

Now, I doubt this is standard practice, but if someone is looking to reduce the amount of code in their route declarations, this is one way to do it.现在,我怀疑这是标准做法,但如果有人希望减少路由声明中的代码量,这是一种方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM