关于python:__future__如何在引擎下工作

How __future__ imports work under the hood

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

最有趣的是怎么做

1
from __future__ import print_function

使您能够使用print(而不是print_function,就像您希望其他任何正常的导入一样)。

我已经读过python中的"未来"是什么,以及如何/何时使用它,以及它是如何彻底工作的,尤其是遇到了一个特定的行:

A future statement is a directive to the compiler that a particular
module should be compiled using syntax or semantics that will be
available in a specified future release of Python.

我很想知道是什么让这一切成为可能。尤其是像

1
from __future__ import division

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

1
from __future__ import barry_as_FLUFL

可以在python3上启用<>语法(我觉得最有趣的是,为了向后兼容,您必须从"__future__导入一个特性)。

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


from __future__ import print_function告诉解析器不要将print当作关键字(将其保留为名称)。这样编译器就把它当作函数而不是语句。

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

这主要在future.c源文件中处理,该文件有一个future_parse()函数,用于检查import fromast对象,其中module参数设置为__future__并根据找到的内容设置标志。

例如,对于barry_as_FLUFL功能,解析器拒绝!=作为语法,而是接受<>作为语法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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;
    }
}

您可以通过对compile.h中列出的FUTURE_*标志进行grepping来找到其他示例。

请注意,有一个__future__python模块,但它不直接参与代码的解析和编译;它只是为了让python代码轻松访问有关指令的元数据(包括要传递给compile()函数的flags参数的位域值),没有其他功能。