__future__进口如何在引擎盖下工作
问题内容:
我一直对__future__
模块着迷,特别是它更改python语句解析方式的能力。
最有趣的是如何做类似的事情
from __future__ import print_function
使您可以使用print
(而不是print_function
,就像您期望其他任何正常导入一样)。
我已经阅读了Python中的__future__是什么,以及如何/何时使用它,以及它是如何工作的,特别是遇到了特定的问题:
将来的语句向编译器发出指令,指示应使用在将来指定的Python版本中可用的语法或语义来编译特定的模块。
我很想知道真正使之成为可能的复杂性。特别是怎么样
from __future__ import division
可以在python2上启用真正的除法,而
from __future__ import barry_as_FLUFL
可以<>
在python3上启用语法(我觉得最有趣的是,您必须从“ __future__
”导入功能以实现向后兼容)。
总之,总而言之,我想知道__future__
在导入指令或其伪像时编译器如何理解和执行该指令。
问题答案:
from __future__ import print_function
告诉解析器不要将其print
视为关键字(而是将其保留为名称)。这样,编译器将其视为函数而不是语句。
为了对此进行跟踪,该compiler
结构具有一个c_future
字段,该字段包含一个PyFutureFeatures
对象,该对象跟踪已启用了哪些将来的指令。解析器和编译器的各个部分检查标志并更改行为。
这主要在future.c
源文件中处理,该源文件具有检查模块参数设置为的AST对象的future_parse()
功能,并根据找到的内容设置标志。import from``__future__
例如,对于barry_as_FLUFL
“功能”,解析器拒绝!=
为语法,但接受<>
,而不是:
if (type == NOTEQUAL) {
if (!(ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
strcmp(str, "!=")) {
PyObject_FREE(str);
err_ret->error = E_SYNTAX;
break;
}
else if ((ps->p_flags & CO_FUTURE_BARRY_AS_BDFL) &&
strcmp(str, "<>")) {
PyObject_FREE(str);
err_ret->text = "with Barry as BDFL, use '<>' "
"instead of '!='";
err_ret->error = E_SYNTAX;
break;
}
}
您可以通过grepping中列出的FUTURE_*
标志找到其他示例。compile.h
注意,这里有一个__future__
Python模块,但是它并不直接参与代码的解析和编译。仅仅是为了使Python代码可以轻松访问有关指令的元数据(包括传递给函数flags
参数的位域值),仅此而已。compile()