本人 java 开发最近自学 python,web 项目框架
flask 使用了注解来注册路径
@app.route("/")
def hello():
return "Hello World!"
django 中则是
urlpatterns = [
path('admin/', admin.site.urls)
]
问题 1:
flask 中注解是怎么实现注册的?注解的代码是在方法被调用的时候才会触发吧?那么他是怎么在项目初始化的时候注册映射的呢?
问题 2:
我喜欢注解,就想着是不是可以自己写个注解来让 django 也可以使用注解注册?其实解答了疑问 1,理论上问题 2 也就回答了吧。
1
neoblackcap 2018-12-03 18:19:29 +08:00 via iPhone
那个不是注解,Python 没有注解,那个是装饰器,要打比方也是高阶函数。
跟 Java 注解对 bytecode 下手不一样 |
2
vissssa 2018-12-03 18:21:37 +08:00
本质上是注册方法的简写
> self.add_url_rule(rule, endpoint, f, **options) |
3
rizon OP @neoblackcap #1 嗯,是的,我也发现我理解有误,python 里面这个叫做 Decorators 的东西,其实就是在函数外面包装了一层或多层函数?
那么 flask 是怎么利用这个东西实现的呢?还在翻源码研究,, |
4
rizon OP @vissssa #2 是,可是我不理解的是,这个 app.route() 方法是什么时候会被触发?我理解的是,python 的修饰器是在方法被执行的时候才会执行吧?
|
5
misaka19000 2018-12-03 18:41:28 +08:00
|
6
hahastudio 2018-12-03 18:47:38 +08:00
|
7
wwqgtxx 2018-12-03 19:11:28 +08:00
@app.route("/")
def hello(): ----return "Hello World!" 这个代码等价于 def hello(): ----return "Hello World!" hello = app.route("/")(hello) |
9
XIVN1987 2018-12-03 19:12:47 +08:00
我觉得就是在执行的时候注册的,,
没读过 CPython 的源码,不过读过 micropython 的源码,,感觉原理应该是类似的 micropython 解释器遇到 def hello()语句时,就会执行指令 MP_BC_MAKE_FUNCTION,,我觉得应该也是在执行的时候遇到 @app.route("/")语句时执行相应的字节码完成注册的 至于装饰器语法本身,可以看看《 Fluent Python 》(中文翻译《流畅的 Python 》),,这本书对 Python 的高级语法讲解的非常好 |
10
XIVN1987 2018-12-03 19:19:05 +08:00
|
13
rizon OP @hahastudio #6 谢谢,看了,可还是不能理解。我 debug 代码的时候
```python def decorator(f): endpoint = options.pop('endpoint', None) self.add_url_rule(rule, endpoint, f, **options) return f ``` 这个方法被执行了,但是为什么会被执行还是不能理解。 |
14
neoblackcap 2018-12-03 20:37:46 +08:00
@rizon 因为你后面再输入`(hello)`的时候已经不是原来的函数执行了,python 一个文件即是一个模块,模块被引用的时候,会解释执行里面的代码,函数声明不会被触发。但是上面已经说了
```python @app.route("/") def hello(): ----return "Hello World!" 这个代码等价于 def hello(): ----return "Hello World!" hello = app.route("/")(hello) <- 这里才是关键,这里代码已经被解释执行了!在这里面路由已经完成了注册 ``` 假如你的 flask 项目是分模块的,如果不引入对应的模块,以及对应的视图函数,那么路由就会注册不成功。 |
15
HelloAmadeus 2018-12-03 20:43:21 +08:00 via Android
装饰器是一个函数,只接受一个参数,返回一个函数,用 @装饰函数,在 import 模块时候运行一次。用处嘛,就大概是 java 里面向切面编程,将一些通用的逻辑插到函数里。
flask 那个 app.route 装饰器就是在你 import 的时候,注册好了路由 |
16
huadi 2018-12-03 21:00:03 +08:00
你用百度的吧? Google 上 python decorator 关键字很容易就找到答案了啊!
|
17
lniwn 2018-12-03 21:09:19 +08:00 via iPhone
@neoblackcap 小小的纠正下,不能说 python 没有注解,python 的注解是用来标注函数参数和返回值类型的,供 ide 做静态分析用,可选。
|
18
freakxx 2018-12-03 21:35:37 +08:00
|
19
rizon OP @neoblackcap #14
@wwqgtxx #7 这事我终于整明白了,带参数的修饰器和不带参数的修饰器是不一样的。。 带参数修饰器会在初始化时就执行修饰器的代码并将方法体重新赋值给方法名。 不带参数修饰器在初始化的时候会将方法名赋值给修饰器方法,修饰器方法内部来手动调用被修饰的方法。 |
20
wwqgtxx 2018-12-03 21:39:00 +08:00 via iPhone
@rizon 你要理解 python 中函数是一类对象,一个函数是可以返回另一个函数作为返回值的,所以后面的(hello)并不是一个声明,而是一个链式函数调用,即 app.route('/')返回了一个函数,而后面的(hello)是用 hello 作为参数传递给个该函数,最后结果是再返回一个函数赋值给 hello,当然在 app.route 的这个地方,最后 hello 是没变的,但是实际上也可以完全不返回原函数,而返回另一个
|
21
freakxx 2018-12-03 21:42:01 +08:00
|
22
wwqgtxx 2018-12-03 21:42:11 +08:00
@rizon 刚看到你 19#的回复,再说一下,传递的永远是个 function object 而不是什么“方法名”,只不过“带参数修饰器”本身需要返回一个函数,这个函数接受一个 callable 对象,而“不带参数修饰器”直接就是上面说的那个函数
|
24
xpresslink 2018-12-03 22:00:07 +08:00
@符号在 java 中是注解功能并不是实质功能,但是在 python 中 @后面跟的是装饰器,其实就是一个高阶函数,对下面的函数装饰,过程是把下面的函数当参数处理一下再输出一个处理过的函数。
python 程序的执行过程是先把源码编译成字节码,然后再用解释器解释执行字节码。 python 装饰器不是执行时调用的,而是在编译字节码的过程中就调用处理了,实际上相当于语法糖。 |