__future__ is a standard module added to Python in
version 2.1, the purpose of which is to aid programmers in making a
transition to an upcoming language feature that will be
backwards-incompatible. As usual, the leading and trailing double
underscore in the name means it is reserved, and as is often the case
with such identifiers, implies there be magic here. And in this
case, is there ever!
If you inspect the contents of __future__.py, all you will see is a list
of names of features that have been added to the language, along with two
version tuples (in the form of sys.version) and an arcane integer that,
from its name, belies some connection to the creation of code objects.
And you'll say Big Wow! (Well, if you're from the 1960s,
you will.)
But the
magic
is in the fact that importing any of those feature names
from that module, with a __future__ statement, will cause
the compiler to begin parsing, and emitting
code for, a different language than otherwise; namely, a future version
of Python in which that feature will be standard[1].
A __future__ statement is a particular form of the import statement.
It must use the
from <module> import <name> form,
it must import a
name that the compiler knows is a future feature, and it must not be preceded
in the source by any other statement (except, perhaps, another __future__
statement). This is because __future__ statements are one of the rare
statements (only the second one, actually, the other being
global) that are not executable at run-time. They affect the
entirety of the module they appear in, and thus must have their effect upon
the compiler before it sees any code. Note that the statement
import __future__
while legal (and useful for introspective purposes), is
not a
__future__ statement, and in particular, is not the equivalent of including
a __future__ statement for each feature defined in __future__.py.
I'll explain how it works by way of an example. With the advent of Python
version 2.2, the use of generator functions is available as a __future__
feature. It is anticipated that they will be standard in version 2.3.
They require a __future__ statement because they make yield
a keyword in the language, where it wasn't one before. So, they are not
available in Python 2.2 unless this __future__ statement is uttered:
from __future__ import generators
and without it,
yield remains usable as an
identifier. However, if you use
yield absent that
__future__ statement, you'll get a warning that your code will be in error
in a future version of Python. Notice the progression here:
liberty> python2.1
Python 2.1 (#1, Apr 30 2001, 09:13:37)
[GCC 2.95.2 19991024 (release)] on linux2
Type "copyright", "credits" or "license" for more information.
>>> yield = 1
liberty> python2.2
Python 2.2 (#1, Dec 22 2001, 22:11:33)
[GCC 2.95.2 19991024 (release)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> def a(): yield 1
<string>:1: Warning: 'yield' will become a reserved keyword in the future
File "<string>", line 1
def a(): yield 1
SyntaxError: invalid syntax
>>> yield = 1
<string>:1: Warning: 'yield' will become a reserved keyword in the future
liberty> python2.2
Python 2.2 (#1, Dec 22 2001, 22:11:33)
[GCC 2.95.2 19991024 (release)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import generators
>>> yield = 1
File "<string>", line 1
yield = 1
SyntaxError: invalid syntax
>>> def a(): yield 1
>>>
In version 2.1,
yield had no significance in the language
and was usable as a normal identifier. In version 2.2, it can still be
used as an identifier, and there is no
yield statement.
However, the programmer is warned of change in the wind. If you import
the generator feature from __future__ however,
yield is
then a statement and its use as an identifier becomes a syntax error.
[1] Well, not wholly true. What it actually does is add that future
feature to the version of Python it was prepared to parse already. If there
are more than one feature being added at the same time, you can import only
one with each __future__ statement. That is, you're electing to use particular
future features, not the entire future language.