__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()