__future__ 进口如何在幕后工作
Posted
技术标签:
【中文标题】__future__ 进口如何在幕后工作【英文标题】:How __future__ imports work under the hood 【发布时间】:2018-01-29 18:56:10 【问题描述】:__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,特别是遇到了一行:
Future 语句是对编译器的一个指令,即特定的 模块应该使用将被编译的语法或语义 在指定的 Python 未来版本中可用。
我很想知道究竟是什么让这成为可能。特别是像
from __future__ import division
可以在python2上启用真正的除法,而
from __future__ import barry_as_FLUFL
可以在 python3 上启用<>
语法(我觉得最有趣的是你必须从“__future__
”导入一个特性才能向后兼容)。
总之,我想知道当__future__
或其人工制品被导入时,编译器是如何理解和执行指令的。
【问题讨论】:
因为它不是正常导入。见docs.python.org/2/reference/simple_stmts.html#future @jonrsharpe "总之,我想知道当 future 或其人工制品被导入时,编译器是如何理解和执行指令的。“我已经完成了我的研究,但无论如何感谢您的反对。 我可能应该更改标题以阻止注意力持续时间短的人投反对票。 无论我的意见是否值得,我觉得这个问题肯定有一些肉。 @Ev.Kounis 这 3 名反对者和 1 名密切投票者会不同意,但无论如何,就像我说的那样......可能是我最初的糟糕标题的错。 【参考方案1】:from __future__ import print_function
告诉解析器not treat print
as a keyword(将其保留为名称)。这样编译器会将其视为函数而不是语句。
为了跟踪这一点,compiler
结构有一个 c_future
字段,其中包含一个 PyFutureFeatures
对象,该对象跟踪哪些未来指令已启用。解析器和编译器的各个部分检查标志并改变行为。
这主要在future.c
source file 中处理,它有一个future_parse()
function,用于检查模块参数设置为__future__
的import from
AST 对象,并根据找到的内容设置标志。
例如,对于barry_as_FLUFL
'特征',解析器refuses !=
as syntax but accepts <>
instead:
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_*
标志listed in compile.h
来找到其他示例。
注意有__future__
Python module,但不直接参与代码的解析和编译;它只是为了让 Python 代码轻松访问有关指令的元数据(包括传递给 compile()
function 的 flags
参数的位域值),仅此而已。
【讨论】:
我已经知道了。我想知道它是如何在幕后工作的……这就是这个问题的目的。 @cᴏʟᴅsᴘᴇᴇᴅ:这......相当广泛,但我会看看我能填写什么。 我觉得 barry 最有趣的是他必须来自__future__
,而不是像__past__
这样更明智的人。感谢您一如既往的出色回答。以上是关于__future__ 进口如何在幕后工作的主要内容,如果未能解决你的问题,请参考以下文章
如何使用:从 __future__ 使用 django 导入部门