如何__future__进口工作

cs9*_*s95 4 python import compiler-directives python-2.7 python-internals

我对__future__模块很着迷- 特别是它能够改变在python中解析语句的方式.

最有趣的是如何做类似的事情

from __future__ import print_function
Run Code Online (Sandbox Code Playgroud)

使您可以使用print(而不是print_function像您期望的任何其他正常导入一样).

我已经阅读了Python中使用的__future__是什么以及如何/何时使用它,以及它如何彻底运行,特别是遇到了一个特定的行:

未来的声明是编译器的一个指令,即应该使用将在Python的指定未来版本中提供的语法或语义来编译特定模块.

我很想知道究竟是什么使这成为可能的复杂性.特别是,怎么样

from __future__ import division
Run Code Online (Sandbox Code Playgroud)

可以在python2上启用真正的除法

from __future__ import barry_as_FLUFL
Run Code Online (Sandbox Code Playgroud)

可以<>在python3上启用语法(我发现最有趣的是你必须从" __future__" 导入一个功能以实现向后兼容).

无论如何,总而言之,我想知道编译器在__future__导入它的人工制品时如何理解和执行该指令.

Mar*_*ers 7

from __future__ import print_function告诉解析器不要将其print视为关键字(而是将其作为名称).这样编译器将其视为函数而不是语句.

为了跟踪这一点,compilerstruct有一个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;
    }
}
Run Code Online (Sandbox Code Playgroud)

您可以通过grepping中列出FUTURE_*标志找到其他示例.compile.h

请注意,有一个__future__Python模块,但它不直接参与代码的解析和编译; 它只是让Python代码轻松访问有关指令的元数据(包括传递给函数flags参数的位域值),仅此而已.compile()