GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing peps.python.org — PEP 236 – Back to the __future__ | peps.python.org
PEP 236 – Back to the __future__
PEP 236 – Back to the __future__
Table of Contents
MotivationFrom time to time, Python makes an incompatible change to the advertised semantics of core language constructs, or changes their accidental (implementation-dependent) behavior in some way. While this is never done capriciously, and is always done with the aim of improving the language over the long term, over the short term it’s contentious and disrupting. PEP 5, Guidelines for Language Evolution suggests ways to ease the pain, and this PEP introduces some machinery in support of that. PEP 227, Statically Nested Scopes is the first application, and will be used as an example here. Intent[Note: This is policy, and so should eventually move into PEP 5] When an incompatible change to core language syntax or semantics is being made:
So old code continues to work by default, for at least one release, although it may start to generate new warning messages. Migration to the new syntax or semantics can proceed during that time, using the future_statement to make modules containing it act as if the new syntax or semantics were already being enforced. Note that there is no need to involve the future_statement machinery in new features unless they can break existing code; fully backward- compatible additions can– and should –be introduced without a corresponding future_statement. SyntaxA future_statement is simply a from/import statement using the reserved module
name future_statement: "from" "__future__" "import" feature ["as" name] (","feature ["as" name])* feature: identifier name: identifier In addition, all future_statements must appear near the top of the module. The only lines that can appear before a future_statement are:
Example: """This is a module docstring.""" # This is a comment, preceded by a blank line and followed by # a future_statement. from __future__ import nested_scopes from math import sin from __future__ import alabaster_weenoblobs # compile-time error! # That was an error because preceded by a non-future_statement. SemanticsA future_statement is recognized and treated specially at compile time: changes to the semantics of core constructs are often implemented by generating different code. It may even be the case that a new feature introduces new incompatible syntax (such as a new reserved word), in which case the compiler may need to parse the module differently. Such decisions cannot be pushed off until runtime. For any given release, the compiler knows which feature names have been defined, and raises a compile-time error if a future_statement contains a feature not known to it [2]. The direct runtime semantics are the same as for any The interesting runtime semantics depend on the specific feature(s) “imported” by the future_statement(s) appearing in the module. Note that there is nothing special about the statement: import __future__ [as name] That is not a future_statement; it’s an ordinary import statement, with no special semantics or syntax restrictions. ExampleConsider this code, in file scope.py: x = 42 def f(): x = 666 def g(): print "x is", x g() f() Under 2.0, it prints: x is 42 Nested scopes (PEP 227) are being introduced in 2.1. But under 2.1, it still prints: x is 42 and also generates a warning. In 2.2, and also in 2.1 if x is 666 Standard Module __future__.py
Each statement in FeatureName = "_Feature(" OptionalRelease "," MandatoryRelease ")" where, normally, OptionalRelease < MandatoryRelease, and both are
5-tuples of the same form as (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 records the first release in which: from __future__ import FeatureName was accepted. In the case of MandatoryReleases that have not yet occurred, MandatoryRelease predicts the release in which the feature will become part of the language. Else MandatoryRelease records when the feature became part of the language; in releases at or after that, modules no longer need: from __future__ import FeatureName to use the feature in question, but may continue to use such imports. MandatoryRelease may also be Instances of No feature line will ever be deleted from Example line: nested_scopes = _Feature((2, 1, 0, "beta", 1), (2, 2, 0, "final", 0)) This means that: from __future__ import nested_scopes will work in all releases at or after 2.1b1, and that nested_scopes are intended to be enforced starting in release 2.2. Resolved Problem: Runtime CompilationSeveral Python features can compile code during a module’s runtime:
Since a module M containing a future_statement naming feature F explicitly requests that the current release act like a future release with respect to F, any code compiled dynamically from text passed to one of these from within M should probably also use the new syntax or semantics associated with F. The 2.1 release does behave this way. This isn’t always desired, though. For example, In any case, a future_statement appearing “near the top” (see Syntax above) of
text compiled dynamically by an Resolved Problem: Native Interactive ShellsThere are two ways to get an interactive shell:
An interactive shell can be seen as an extreme case of runtime compilation
(see above): in effect, each statement typed at an interactive shell prompt
runs a new instance of Resolved Problem: Simulated Interactive ShellsInteractive shells “built by hand” (by tools such as IDLE and the Emacs Python-mode) should behave like native interactive shells (see above). However, the machinery used internally by native interactive shells has not been exposed, and there isn’t a clear way for tools building their own interactive shells to achieve the desired behavior. NOTE: PEP 264 later addressed this, by adding intelligence to the standard
Questions and AnswersWhat about a “from __past__” version, to get back old behavior?Outside the scope of this PEP. Seems unlikely to the author, though. Write a PEP if you want to pursue it. What about incompatibilities due to changes in the Python virtual machine?Outside the scope of this PEP, although PEP 5 suggests a grace period there too, and the future_statement may also have a role to play there. What about incompatibilities due to changes in Python’s C API?Outside the scope of this PEP. I want to wrap future_statements in try/except blocks, so I can use different code depending on which version of Python I’m running. Why can’t I?Sorry! Note that you can import Going back to the nested_scopes example, what if release 2.2 comes along and I still haven’t changed my code? How can I keep the 2.1 behavior then?By continuing to use 2.1, and not moving to 2.2 until you do change your code. The purpose of future_statement is to make life easier for people who keep current with the latest release in a timely fashion. We don’t hate you if you don’t, but your problems are much harder to solve, and somebody with those problems will need to write a PEP addressing them. future_statement is aimed at a different audience. Overloading
|
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |