Python 中的__ future__ 是用来做什么的,以及如何/何时使用它,以及它是如何工作的

__future__经常出现在 Python 模块中。即使在阅读了 巨蟒的 __future__文档之后,我仍然不明白 __future__的用途以及如何/何时使用它。

有人能举例说明吗?

我收到的一些关于 __future__基本用法的回答似乎是正确的。

然而,关于 __future__的工作原理,我还需要了解一件事:

对我来说,最令人困惑的概念是当前的 Python 版本如何包含未来版本的特性,以及使用未来版本的特性的程序如何能够在当前版本的 Python 中成功编译。

我猜测当前的版本包含了未来的潜在特性。但是,这些特性只能通过使用 __future__来获得,因为它们不是当前的标准。如果我是对的,请告诉我。

385094 次浏览

通过__future__模块的包含,您可以慢慢习惯不兼容的更改或引入新关键字的更改。

例如,为了使用上下文管理器,你必须在2.5中执行from __future__ import with_statement,因为with关键字是新的,不应该再用作变量名。为了在Python 2.5或更早版本中使用with作为Python关键字,你需要使用上面的导入。

另一个例子是

from __future__ import divisionprint 8/7  # prints 1.1428571428571428print 8//7 # prints 1

如果没有__future__的东西,两个print语句都会打印1

内部区别在于,如果没有该导入,/映射到__div__()方法,而使用它,__truediv__()被使用。(无论如何,//调用__floordiv__()。)

Aproposprintprint在3. x中变成了一个函数,失去了作为关键字的特殊属性。所以情况正好相反。

>>> print
>>> from __future__ import print_function>>> print<built-in function print>>>>

当你这么做的时候

from __future__ import whatever

您实际上并没有使用import语句,而是使用了未来声明语句。您正在阅读错误的文档,因为您实际上并没有导入该模块。

未来的语句是特殊的——它们会改变你的Python模块的解析方式,这就是为什么它们必须位于文件顶部。它们为文件中的单词或符号赋予了新的或不同的含义。来自文档:

未来语句是对编译器的指令,指示应使用将在指定的未来Python版本中可用的语法或语义学编译特定模块。未来语句旨在简化向引入语言不兼容更改的未来Python版本的迁移。它允许在功能成为标准版本之前在每个模块的基础上使用新功能。

如果你真的想导入__future__模块,就这样做

import __future__

然后像往常一样访问它。

它可用于使用将出现在较新版本中的功能,同时具有较旧的Python版本。

例如

>>> from __future__ import print_function

将允许您使用print作为函数:

>>> print('# of entries', len(dictionary), file=sys.stderr)

或者就像说“由于这是python v2.7,请使用在python 3中添加后也添加到python v2.7中的不同的'print'函数。所以我的'print'将不再是语句(例如print“消息”)而是函数(例如print(“消息”,选项)。这样当我的代码在python 3中运行时,'print'就不会中断。”

from __future__ import print_function

print_function是包含“print”的新实现的模块,根据它在python v3中的行为。

这有更多的解释:http://python3porting.com/noconv.html

__future__是一个伪模块,程序员可以使用它来启用与当前解释器不兼容的新语言功能。例如,表达式11/4当前的计算结果为2。如果执行它的模块通过执行以下命令启用了真除法:

from __future__ import division

表达式11/4将计算为2.75。通过导入__future__模块并计算其变量,您可以看到新功能何时首次添加到语言中以及何时成为默认值:

>>> import __future__>>> __future__.division_Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)

我发现非常有用的用途之一是print_function from__future__模块。

在Python 2.7中,我希望来自不同打印语句的字符打印在同一行上,没有空格。

可以在末尾使用逗号(",")来完成,但它也会附加一个额外的空格。上述语句用作:

from __future__ import print_function...print (v_num,end="")...

这将在没有空格的单行中打印每次迭代的v_num值。

在Python 3.0之后,print不再只是一个语句,而是一个函数。并包含在PEP 3105中。

此外,我认为Python 3.0包仍然具有这些特殊功能。让我们通过Python中传统的“PyramidProgram”来看看它的可用性:

from __future__ import print_function
class Star(object):def __init__(self,count):self.count = count
def start(self):for i in range(1,self.count):for j in range (i):print('*', end='') # PEP 3105: print As a Functionprint()
a = Star(5)a.start()
Output:**********

如果我们使用普通的print函数,我们将无法实现相同的输出,因为print()带有额外的换行符。所以每次内部for循环执行时,它都会将*打印到下一行。

已经有一些很好的答案,但没有一个解决__future__语句当前支持的完整列表。

简单地说,#0语句强制Python解释器使用该语言的新特性。


它目前支持的功能如下:

nested_scopes

在Python 2.1之前,以下代码会引发名称错误

def f():...def g(value):...return g(value-1) + 1...

from __future__ import nested_scopes指令将允许启用此功能。

generators

引入了生成器函数,例如下面的函数,用于在连续的函数调用之间保存状态:

def fib():a, b = 0, 1while 1:yield ba, b = b, a+b

division

经典除法在Python 2. x版本中使用。这意味着一些除法语句返回除法的合理近似值(“真除法”),而其他语句返回地板(“地板除法”)。从Python 3.0开始,真正的除法由x/y指定,而地板除法由x//y指定。

from __future__ import division指令强制使用Python 3.0样式划分。

absolute_import

允许用括号括住多个import语句。例如:

from Tkinter import (Tk, Frame, Button, Entry, Canvas, Text,LEFT, DISABLED, NORMAL, RIDGE, END)

而不是:

from Tkinter import Tk, Frame, Button, Entry, Canvas, Text, \LEFT, DISABLED, NORMAL, RIDGE, END

或:

from Tkinter import Tk, Frame, Button, Entry, Canvas, Textfrom Tkinter import LEFT, DISABLED, NORMAL, RIDGE, END

with_statement

在Python中添加语句with作为关键字,以消除对try/finally语句的需求。这在执行文件I/O时的常见用途,例如:

with open('workfile', 'r') as f:read_data = f.read()

print_function

强制使用Python 3括号样式print()函数调用而不是print MESSAGE样式语句。

unicode_literals

介绍bytes对象的文字语法。这意味着像bytes('Hello world', 'ascii')这样的语句可以简单地表示为b'Hello world'

generator_stop

将生成器函数中使用的StopIteration异常的使用替换为RuntimeError异常。

上面没有提到的另一个用途是__future__语句还需要使用Python 2.1+解释器,因为使用旧版本会引发运行时异常。


参考文献

__future__是python模块。添加它是为了避免混淆分析导入语句并期望找到它们正在导入的模块的现有工具。它是在2.1版中添加的,因此如果在2.1版之前使用__future__的导入将失败。

现在看看这段代码:

>>> from __future__ import division>>> division_Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 131072)

_Feature(OptionalRelease, MandatoryRelease, CompilerFlag)的格式返回。可选发布任务发布都是5元组的形式:

(PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an intPY_MINOR_VERSION, # the 1; an intPY_MICRO_VERSION, # the 0; an intPY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; stringPY_RELEASE_SERIAL # the 3; an int)

所以在我们的例子中,OptionalRelease是2.2.0a2,MandatoryRelease是3.0.0a0。

可选发布告诉我们该功能何时被接受的第一个版本。

任务发布预测该特性何时成为语言的一部分,或显示该特性何时成为语言的一部分;在那时或之后的版本中,模块不再需要未来语句来使用有问题的特性,但可以继续使用此类导入。如果任务发布为无,则放弃该计划的特性。

编译器是应该在第四个参数中传递给内置函数编译的(位域)标志,以在动态编译的代码中启用该功能。此标志存储在_Feature实例的compiler_flag属性中。