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

What is __future__ in Python used for and how/when to use it, and how it works

包括我在内的人都知道在python中有一种叫做__future__的东西,它出现在我读过的很多模块中。像我这样的呆板的人不知道它为什么会在那里,也不知道如何/何时使用它,即使在阅读了Python的__future__文档之后。

有没有用实例来解释?

在基本用法方面,我很快得到了一些答案,看起来都是正确的。

但是,为了进一步了解__future__的工作原理:

我刚刚意识到一个关键的事情,当我试图理解它时,我很困惑,那就是,当前的Python版本如何包含将在未来版本中发布的内容?在未来的python版本中,如何使用新特性的程序能够被当前的python版本成功编译?

所以,我想现在,当前版本已经打包了一些潜在的特性,这些特性将包含在未来的版本中,这是正确的吗?但是这些功能只能由__future__提供,这是因为它还没有成为标准——对吗?


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

例如,对于使用上下文管理器,您必须在2.5中执行from __future__ import with_statement,因为with关键字是新的,不应再用作变量名。为了能够使用一个使用名为with的变量的程序,需要上述import语句。

另一个例子是

1
2
3
from __future__ import division
print 8/7  # prints 1.1428571428571428
print 8//7 # prints 1

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

内部差异是,如果没有导入,/将映射到__div__()方法,而使用__truediv__()方法。(在任何情况下,//呼叫__floordiv__()。)

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

1
2
3
4
5
6
>>> print

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


当你这样做的时候

1
from __future__ import whatever

您实际上并没有使用import语句,而是使用将来的语句。您读错了文档,因为您实际上没有导入该模块。

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

A future statement is a directive to the compiler that a particular module should be compiled using syntax or semantics that will be available in a specified future release of Python. The future statement is intended to ease migration to future versions of Python that introduce incompatible changes to the language. It allows use of the new features on a per-module basis before the release in which the feature becomes standard.

如果您确实想导入__future__模块,只需

1
import __future__

然后像往常一样进入。


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

from __future__ import division

11/4的表达可评价为2.75。通过导入__future__模块并评估其变量,您可以看到新功能是何时首次添加到语言的,以及何时成为默认功能:

1
2
3
  >>> import __future__
  >>> __future__.division
  _Feature((2, 2, 0, 'alpha', 2), (3, 0, 0, 'alpha', 0), 8192)


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

例如

1
>>> from __future__ import print_function

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

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

或者像是说"既然这是Python2.7,那么在Python3中添加它之后,使用同样添加到Python2.7中的不同"print"函数。所以我的"print"不再是语句(如print"message"),而是函数(如print("message",options)。这样,当我的代码在python 3中运行时,"print"就不会中断。"

1
from __future__ import print_function

print_函数是包含"print"的新实现的模块,根据它在Pythonv3中的行为方式。

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


已经有了一些很好的答案,但没有一个能给出__future__声明目前支持的完整列表。

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

它当前支持的功能如下:

nested_scopes

在Python2.1之前,以下代码将引发一个名称错误:

1
2
3
4
5
6
def f():
    ...
    def g(value):
        ...
        return g(value-1) + 1
    ...

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

generators

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

1
2
3
4
5
def fib():
    a, b = 0, 1
    while 1:
       yield b
       a, b = b, a+b

division

Python2.x版本中使用了经典的除法。这意味着一些除法语句返回除法的合理近似值("真除法"),而其他语句返回楼层("楼层除法")。从python 3.0开始,真正的划分由x/y指定,而楼层划分由x//y指定。

from __future__ import division指令强制使用python3.0样式的划分。

absolute_import

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

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

而不是:

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

或:

1
2
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时,例如:

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

print_function

强制使用python 3圆括号样式的print函数调用,而不是print MESSAGE样式的print语句。

unicode_literals

介绍bytes对象的文本语法。也就是说,像bytes('Hello world', 'ascii')这样的陈述可以简单地表示为b'Hello world'

generator_stop

将在生成器函数内部使用的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__模块的print_function

在python 2.7中,我希望不同的打印语句中的字符在同一行上不带空格地打印。

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

1
2
3
4
from __future__ import print_function
...
print (v_num,end="")
...

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


显式优于隐式

1
2
3
from __future__ import braces
  File"<stdin>", line 1
SyntaxError: not a chance

[学分:@mdeous]


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

另外,我认为python 3.0包仍然具有这些特殊的功能。让我们通过Python中的传统"金字塔程序"来了解其可用性:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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循环时,它都会将*打印到下一行。