ChatGPT解决这个技术问题 Extra ChatGPT

Python 中的 __future__ 用于什么以及如何/何时使用它,以及它是如何工作的

__future__ 经常出现在 Python 模块中。即使在阅读 the Python's __future__ doc 之后,我也不明白 __future__ 的用途以及如何/何时使用它。

任何人都可以用例子解释吗?

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

但是,我还需要了解有关 __future__ 工作原理的另一件事:

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

我猜测当前版本包含了未来的潜在功能。但是,这些功能只能通过使用 __future__ 才能使用,因为它们不是当前标准。让我知道我是否正确。

这是未来声明的原始提案。我发现它有助于理解为什么它首先存在,因此自然而然地何时以及如何使用它。 python.org/dev/peps/pep-0236
未来语句是对编译器的指令,应使用将在指定的 Python 未来版本中可用的语法或语义来编译特定模块。未来声明旨在简化向 Python 未来版本的迁移,这些版本会对语言进行不兼容的更改。它允许在功能成为标准的发布之前基于每个模块使用新功能。

M
Michael Kiros

通过包含 __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__()。)

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

>>> print

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

不要忘记from __future__ import braces:p
@zoogleflatt 如果您更喜欢制表符,那么您不了解 PEP 8。强烈建议不要使用制表符...
@glglgl 从技术上讲,它只是说他们是首选。在阅读完为什么会这样之后,我并不完全清楚,我猜是缩进级别完全匹配以使代码更整洁?
@zoogleflatt 这当然也与大多数人使用 4 个空格进行 1 级缩进这一事实有关,出于兼容性原因,一个制表符相当于 8 个空格,并且不鼓励混合制表符和空格(分别,AFAIK,甚至在派3)
@whiteSkar我目前没有更新python 3的最新版本,但我认为它仍在使用中,只是你可能不需要这些相当旧的功能。在 Python 3 中,print 绝对是一个函数,但可能还有其他功能可能使用 __future__。 (编辑:参见 docs.python.org/3/library/__future__.html 仍在使用的地方。)
N
Nabin

当你这样做

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 的运行时影响
e
enzo

__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 是空操作吗?
它有点类似于浏览器世界中的 polyfill
T
Toby Speight

已经有一些很好的答案,但没有一个能完整列出 __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/


假设您处于离线状态,python 如何知道未来版本是否可用?如果您没有在计算机上安装未来版本的 python,它如何使用未来的功能?
@MohsenHaddadi 未来声明有点像一个功能标志......当某些功能被 Python 接受时,这些功能会改变现有程序的行为(例如真正的除法),首先您可以使用未来声明启用它们,并且然后在 未来 版本中,它们成为该语言的永久特征。因此名称为 __future__。我相信这种尽早选择中断更改的能力旨在帮助现有程序在中断更改完全生效之前及时过渡。
我认为这是最好的答案。尤其是答案的开头,“强制”使用“较新的功能”。
很好的答案,我只希望有一个 from __past__ import print,因为我真的很喜欢 Python 2 的 print quick_debug_var 的懒惰
M
Mihai Maruseac

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

例如

>>> from __future__ import print_function

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

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

t
thatoneuser

还是说“因为这是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


T
Timo Tijhof

我发现其中一个非常有用的用途是来自 __future__ 模块的 print_function

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

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

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

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


j
jainakki

__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) 的格式返回。 OptionalReleaseMandatoryRelease 都是 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 属性中。


j
joel goldstick

在 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 循环时,它都会将 * 打印到下一行。