__future__进口如何在引擎盖下工作

时间:2017-08-21 16:06:19

标签: python python-2.7 import python-internals compiler-directives

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

最有趣的是如何做像

这样的事情
from __future__ import print_function

允许您使用print(而不是print_function,就像您期望任何其他正常导入一样。)

我已经彻底阅读了What is __future__ in Python used for and how/when to use it, and how it works,特别是遇到了一个特定的行:

  

未来的声明是指向编译器的特定指令   应该使用将要使用的语法或语义来编译模块   在指定的Python未来版本中提供。

我很想知道究竟是什么让这成为可能的复杂性。尤其是

之类的东西
from __future__ import division

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

from __future__ import barry_as_FLUFL

可以在python3上启用<>语法(我觉得最有趣的是你必须从&#34; __future__&#34;中导入一个功能以实现向后兼容性。)

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

1 个答案:

答案 0 :(得分:7)

from __future__ import print_function告诉解析器not treat print as a keyword(将其保留为名称)。这样编译器将其视为函数而不是语句。

为了跟踪这一点,compiler结构有一个c_future字段,其中包含一个PyFutureFeatures对象,用于跟踪已启用的指令。解析器和编译器的各个部分检查标志并改变行为。

这主要在future.c source file处理,future_parse() functionrefuses != as syntax but accepts <> instead检查import from AST对象,模块参数设置为__future__,并设置标记基于找到了什么。

例如,对于barry_as_FLUFL'功能',解析器listed in compile.h

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;
    }
}

您可以通过点击FUTURE_*标记__future__ Python module找到其他示例。

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