【问题标题】:What is __future__ in Python used for and how/when to use it, and how it worksPython 中的 __future__ 用于什么以及如何/何时使用它,以及它是如何工作的
【发布时间】:2011-10-27 20:28:46
【问题描述】:

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

谁能举例说明?

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

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

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

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

【问题讨论】:

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

标签: python python-2.x


【解决方案1】:

随着__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__()。)

Apropos print: print 在 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,甚至在 Py3 中不允许)
  • @whiteSkar 我目前还没有更新 python 3 的更新版本,但我认为它仍在使用中,只是你可能不需要这些相当旧的功能。在 Python 3 中,print 绝对是一个函数,但可能还有其他功能可能使用__future__。 (编辑:参见docs.python.org/3/library/__future__.html 仍在使用的地方。)
【解决方案2】:

当你这样做时

from __future__ import whatever

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

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

Future 语句是对编译器的指令,指示特定模块应使用特定的 Python 未来版本中可用的语法或语义进行编译。未来声明旨在简化向未来版本的 Python 的迁移,这些版本会对语言进行不兼容的更改。它允许在功能成为标准的发布之前按模块使用新功能。

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

import __future__

然后像往常一样访问它。

【讨论】:

  • 从技术上讲,它也是一个导入语句,因为相关名称绑定到一个局部变量。 from __future__ import print_function 都改变了 print 关键字的行为,并且具有等同于 print_function = __import__("__future__").print_function 的运行时影响
【解决方案3】:

__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
【解决方案4】:

已经有一些很好的答案,但没有一个能完整列出__future__ 语句当前支持的内容。

简单地说,__future__ 语句强制 Python 解释器使用该语言的更新功能。


目前支持的功能如下:

nested_scopes

在 Python 2.1 之前,以下代码会引发 NameError

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

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

generators

引入如下生成器函数来保存连续函数调用之间的状态:

def fib():
    a, b = 0, 1
    while 1:
       yield b
       a, 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, 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'

generator_stop

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

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


参考文献

【讨论】:

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

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

例如

>>> from __future__ import print_function

将允许您将print 用作函数:

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

【讨论】:

    【解决方案6】:

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

    【讨论】:

      【解决方案7】:

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

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

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

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

      这会将每次迭代的v_num 的值打印在一行中,不带空格。

      【讨论】:

        【解决方案8】:

        __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 属性中。

        【讨论】:

          【解决方案9】:

          在 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() 带有一个额外的换行符。所以每次内部for循环执行时,都会在下一行打印*。

          【讨论】:

            猜你喜欢
            • 2020-08-06
            • 1970-01-01
            • 2013-01-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多