__future__
经常出现在 Python 模块中。即使在阅读 the Python's __future__
doc 之后,我也不明白 __future__
的用途以及如何/何时使用它。
任何人都可以用例子解释吗?
我收到的关于 __future__
基本用法的一些答案似乎是正确的。
但是,我还需要了解有关 __future__
工作原理的另一件事:
对我来说最令人困惑的概念是当前的 Python 版本如何包含未来版本的功能,以及如何在当前版本的 Python 中成功编译使用来自未来版本的功能的程序。
我猜测当前版本包含了未来的潜在功能。但是,这些功能只能通过使用 __future__
才能使用,因为它们不是当前标准。让我知道我是否正确。
通过包含 __future__
模块,您可以慢慢习惯不兼容的更改或引入新关键字的更改。
例如,为了使用上下文管理器,您必须在 2.5 中使用 from __future__ import with_statement
,因为 with
关键字是新的,不应再用作变量名。为了在 Python 2.5 或更早版本中使用 with
作为 Python 关键字,您需要使用上述导入。
另一个例子是
from __future__ import division
print 8/7 # prints 1.1428571428571428
print 8//7 # prints 1
如果没有 __future__
的东西,两个 print
语句都会打印 1
。
内部区别在于,如果没有该导入,/
将映射到 __div__()
方法,而有了它,则使用 __truediv__()
。 (无论如何,//
调用 __floordiv__()
。)
恰如其分 print
:print
在 3.x 中变成了一个函数,失去了它作为关键字的特殊属性。所以情况正好相反。
>>> print
>>> from __future__ import print_function
>>> print
<built-in function print>
>>>
当你这样做
from __future__ import whatever
您实际上使用的不是 import
语句,而是 future statement。您正在阅读错误的文档,因为您实际上并没有导入该模块。
未来的语句很特别——它们改变了 Python 模块的解析方式,这就是为什么它们必须位于文件顶部的原因。它们为文件中的单词或符号赋予新的或不同的含义。从文档:
未来语句是对编译器的指令,应使用将在指定的 Python 未来版本中可用的语法或语义来编译特定模块。未来声明旨在简化向 Python 未来版本的迁移,这些版本会对语言进行不兼容的更改。它允许在功能成为标准的发布之前基于每个模块使用新功能。
如果您确实想导入 __future__
模块,只需执行
import __future__
然后像往常一样访问它。
from __future__ import print_function
既改变了 print
关键字的行为,又具有相当于 print_function = __import__("__future__").print_function
的运行时影响
__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)
import __future__ xyz
是空操作吗?
已经有一些很好的答案,但没有一个能完整列出 __future__
语句当前支持的内容。
简而言之,__future__
语句强制 Python 解释器使用该语言的更新功能。
它目前支持的功能如下:
嵌套范围
在 Python 2.1 之前,以下代码会引发 NameError:
def f():
...
def g(value):
...
return g(value-1) + 1
...
from __future__ import nested_scopes
指令将允许启用此功能。
发电机
引入了如下生成器函数来保存连续函数调用之间的状态:
def fib():
a, b = 0, 1
while 1:
yield b
a, b = b, a+b
分配
经典除法用于 Python 2.x 版本。这意味着一些除法语句返回一个合理的除法近似值(“真除法”),而另一些则返回下限(“下除法”)。从 Python 3.0 开始,真正的除法由 x/y
指定,而地板除法由 x//y
指定。
from __future__ import division
指令强制使用 Python 3.0 样式划分。
绝对导入
允许括号括起多个 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, Text
from 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'
。
发电机停止
将在生成器函数中使用的 StopIteration
异常替换为 RuntimeError
异常。
上面没有提到的另一个用途是 __future__
语句还需要使用 Python 2.1+ 解释器,因为使用旧版本会引发运行时异常。
参考
https://docs.python.org/2/library/future.html
https://docs.python.org/3/library/future.html
https://docs.python.org/2.2/whatsnew/node9.html
https://www.python.org/dev/peps/pep-0255/
https://www.python.org/dev/peps/pep-0238/
https://www.python.org/dev/peps/pep-0328/
https://www.python.org/dev/peps/pep-3112/
https://www.python.org/dev/peps/pep-0479/
__future__
。我相信这种尽早选择中断更改的能力旨在帮助现有程序在中断更改完全生效之前及时过渡。
from __past__ import print
,因为我真的很喜欢 Python 2 的 print quick_debug_var
的懒惰
它可用于使用将出现在较新版本中的功能,同时具有较旧版本的 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 "message" )但函数(例如 print("message", options)。那样当我的代码在 python 3 中运行时,'print' 不会中断。
在
from __future__ import print_function
print_function 是包含 'print' 的新实现的模块,根据它在 python v3 中的行为方式。
这有更多解释:http://python3porting.com/noconv.html
我发现其中一个非常有用的用途是来自 __future__
模块的 print_function
。
在 Python 2.7 中,我希望将不同打印语句中的字符打印在同一行上而没有空格。
它可以在末尾使用逗号(“,”)来完成,但它也会附加一个额外的空格。上述语句当用作:
from __future__ import print_function
...
print (v_num,end="")
...
这将在没有空格的单行中打印每次迭代的 v_num
的值。
__future__
是一个 Python module。添加它是为了避免混淆分析导入语句并期望找到它们正在导入的模块的现有工具。它是在 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)
的格式返回。 OptionalRelease 和 MandatoryRelease 都是 5 元组,形式为:
(
PY_MAJOR_VERSION, # the 2 in 2.1.0a3; an int
PY_MINOR_VERSION, # the 1; an int
PY_MICRO_VERSION, # the 0; an int
PY_RELEASE_LEVEL, # "alpha", "beta", "candidate" or "final"; string
PY_RELEASE_SERIAL # the 3; an int
)
所以在我们的例子中,OptionalRelease 是 2.2.0a2,MandatoryRelease 是 3.0.0a0。
OptionalRelease 告诉我们该功能被接受时的第一个版本。
MandatoryRelease 预测特征何时成为语言的一部分或显示特征何时成为语言的一部分;在此或之后的版本中,模块不再需要未来声明来使用相关功能,但可以继续使用此类导入。如果 MandatoryRelease 为 None,则删除该计划的功能。
CompilerFlag 是应该在第四个参数中传递给内置函数 compile() 的(位域)标志,以在动态编译的代码中启用该功能。此标志存储在 _Feature 实例的 compiler_flag 属性中。
在 Python 3.0 之后,print 不再只是一个语句,而是一个函数。并包含在 PEP 3105 中。
另外我认为 Python 3.0 包仍然具有这些特殊功能。让我们通过 Python 中的传统“金字塔程序”来看看它的可用性:
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 Function
print()
a = Star(5)
a.start()
Output:
*
**
***
****
如果我们使用普通的 print 函数,我们将无法获得相同的输出,因为 print() 带有一个额外的换行符。所以每次执行内部 for 循环时,它都会将 * 打印到下一行。
from __future__ import braces
:pprint
绝对是一个函数,但可能还有其他功能可能使用__future__
。 (编辑:参见 docs.python.org/3/library/__future__.html 仍在使用的地方。)