__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.

Log in or register to write something here or to contact authors.