Update to reflect pending __future__ PEP, availability in 2.1 and 2.2,
and warnings. Various bugs reported by Aahz Maruch.
This commit is contained in:
parent
910d1b4561
commit
9b6d9b4453
127
pep-0227.txt
127
pep-0227.txt
|
@ -26,13 +26,18 @@ Abstract
|
||||||
Introduction
|
Introduction
|
||||||
|
|
||||||
This proposal changes the rules for resolving free variables in
|
This proposal changes the rules for resolving free variables in
|
||||||
Python functions. The Python 2.0 definition specifies exactly
|
Python functions. The new name resolution semantics will take
|
||||||
three namespaces to check for each name -- the local namespace,
|
effect with Python 2.2. These semantics will also be available in
|
||||||
the global namespace, and the builtin namespace. According to
|
Python 2.1 by adding "from __future__ import nested_scopes" to the
|
||||||
this defintion, if a function A is defined within a function B,
|
top of a module.
|
||||||
the names bound in B are not visible in A. The proposal changes
|
|
||||||
the rules so that names bound in B are visible in A (unless A
|
The Python 2.0 definition specifies exactly three namespaces to
|
||||||
contains a name binding that hides the binding in B).
|
check for each name -- the local namespace, the global namespace,
|
||||||
|
and the builtin namespace. According to this definition, if a
|
||||||
|
function A is defined within a function B, the names bound in B
|
||||||
|
are not visible in A. The proposal changes the rules so that
|
||||||
|
names bound in B are visible in A (unless A contains a name
|
||||||
|
binding that hides the binding in B).
|
||||||
|
|
||||||
The specification introduces rules for lexical scoping that are
|
The specification introduces rules for lexical scoping that are
|
||||||
common in Algol-like languages. The combination of lexical
|
common in Algol-like languages. The combination of lexical
|
||||||
|
@ -62,11 +67,19 @@ Introduction
|
||||||
in crude terms, implements the default argument approach
|
in crude terms, implements the default argument approach
|
||||||
automatically. The "root=root" argument can be omitted.
|
automatically. The "root=root" argument can be omitted.
|
||||||
|
|
||||||
|
The new name resolution semantics will cause some programs to
|
||||||
|
behave differently than they did under Python 2.0. In some cases,
|
||||||
|
programs will fail to compile. In other cases, names that were
|
||||||
|
previously resolved using the global namespace will be resolved
|
||||||
|
using the local namespace of an enclosing function. In Python
|
||||||
|
2.1, warnings will be issued for all program statement that will
|
||||||
|
behave differently.
|
||||||
|
|
||||||
Specification
|
Specification
|
||||||
|
|
||||||
Python is a statically scoped language with block structure, in
|
Python is a statically scoped language with block structure, in
|
||||||
the traditional of Algol. A code block or region, such as a
|
the traditional of Algol. A code block or region, such as a
|
||||||
module, class defintion, or function body, is the basic unit of a
|
module, class definition, or function body, is the basic unit of a
|
||||||
program.
|
program.
|
||||||
|
|
||||||
Names refer to objects. Names are introduced by name binding
|
Names refer to objects. Names are introduced by name binding
|
||||||
|
@ -91,7 +104,8 @@ Specification
|
||||||
module containing the code block, and the builtin namespace, the
|
module containing the code block, and the builtin namespace, the
|
||||||
namespace of the module __builtin__. The global namespace is
|
namespace of the module __builtin__. The global namespace is
|
||||||
searched first. If the name is not found there, the builtin
|
searched first. If the name is not found there, the builtin
|
||||||
namespace is searched.
|
namespace is searched. The global statement must precede all uses
|
||||||
|
of the name.
|
||||||
|
|
||||||
If a name is used within a code block, but it is not bound there
|
If a name is used within a code block, but it is not bound there
|
||||||
and is not declared global, the use is treated as a reference to
|
and is not declared global, the use is treated as a reference to
|
||||||
|
@ -108,7 +122,7 @@ Specification
|
||||||
occur within a block, they introduce new local names in the
|
occur within a block, they introduce new local names in the
|
||||||
current block unless there is also a global declaration.
|
current block unless there is also a global declaration.
|
||||||
|
|
||||||
Function defintion: def name ...
|
Function definition: def name ...
|
||||||
Class definition: class name ...
|
Class definition: class name ...
|
||||||
Assignment statement: name = ...
|
Assignment statement: name = ...
|
||||||
Import statement: import name, import module as name,
|
Import statement: import name, import module as name,
|
||||||
|
@ -126,16 +140,24 @@ Specification
|
||||||
to delete the name. The compiler will raise a SyntaxError for
|
to delete the name. The compiler will raise a SyntaxError for
|
||||||
'del name'.
|
'del name'.
|
||||||
|
|
||||||
If the wildcard form of import (import *) is used in a function
|
If the wild card form of import (import *) is used in a function
|
||||||
and the function contains a nested block with free variables, the
|
and the function contains a nested block with free variables, the
|
||||||
compiler will raise a SyntaxError.
|
compiler will raise a SyntaxError.
|
||||||
|
|
||||||
If exec is used in a function and the function contains a nested
|
If exec is used in a function and the function contains a nested
|
||||||
block with free variables, the compiler will raise a SyntaxError
|
block with free variables, the compiler will raise a SyntaxError
|
||||||
unless the exec explicit specifies the local namespace for the
|
unless the exec explicitly specifies the local namespace for the
|
||||||
exec. (In other words, "exec obj" would be illegal, but
|
exec. (In other words, "exec obj" would be illegal, but
|
||||||
"exec obj in ns" would be legal.)
|
"exec obj in ns" would be legal.)
|
||||||
|
|
||||||
|
If a name bound in a function scope is also the name of a module
|
||||||
|
global name or a standard builtin name and the function contains a
|
||||||
|
nested function scope that references the name, the compiler will
|
||||||
|
issue a warning. The name resolution rules will result in
|
||||||
|
different bindings under Python 2.0 than under Python 2.2. The
|
||||||
|
warning indicates that the program may not run correctly with all
|
||||||
|
versions of Python.
|
||||||
|
|
||||||
Discussion
|
Discussion
|
||||||
|
|
||||||
The specified rules allow names defined in a function to be
|
The specified rules allow names defined in a function to be
|
||||||
|
@ -148,11 +170,11 @@ Discussion
|
||||||
- Variables are not declared.
|
- Variables are not declared.
|
||||||
|
|
||||||
Names in class scope are not accessible. Names are resolved in
|
Names in class scope are not accessible. Names are resolved in
|
||||||
the innermost enclosing function scope. If a class defintion
|
the innermost enclosing function scope. If a class definition
|
||||||
occurs in a chain of nested scopes, the resolution process skips
|
occurs in a chain of nested scopes, the resolution process skips
|
||||||
class definitions. This rule prevents odd interactions between
|
class definitions. This rule prevents odd interactions between
|
||||||
class attributes and local variable access. If a name binding
|
class attributes and local variable access. If a name binding
|
||||||
operation occurs in a class defintion, it creates an attribute on
|
operation occurs in a class definition, it creates an attribute on
|
||||||
the resulting class object. To access this variable in a method,
|
the resulting class object. To access this variable in a method,
|
||||||
or in a function nested within a method, an attribute reference
|
or in a function nested within a method, an attribute reference
|
||||||
must be used, either via self or via the class name.
|
must be used, either via self or via the class name.
|
||||||
|
@ -167,7 +189,7 @@ Discussion
|
||||||
|
|
||||||
The global statement short-circuits the normal rules. Under the
|
The global statement short-circuits the normal rules. Under the
|
||||||
proposal, the global statement has exactly the same effect that it
|
proposal, the global statement has exactly the same effect that it
|
||||||
does for Python 2.0. It's behavior is preserved for backwards
|
does for Python 2.0. Its behavior is preserved for backwards
|
||||||
compatibility. It is also noteworthy because it allows name
|
compatibility. It is also noteworthy because it allows name
|
||||||
binding operations performed in one block to change bindings in
|
binding operations performed in one block to change bindings in
|
||||||
another block (the module).
|
another block (the module).
|
||||||
|
@ -233,8 +255,8 @@ Examples
|
||||||
File "<stdin>", line 1, in ?
|
File "<stdin>", line 1, in ?
|
||||||
AttributeError: _private
|
AttributeError: _private
|
||||||
|
|
||||||
An example from Tim Peters of the potential pitfalls of nested scopes
|
An example from Tim Peters demonstrates the potential pitfalls of
|
||||||
in the absence of declarations:
|
nested scopes in the absence of declarations:
|
||||||
|
|
||||||
i = 6
|
i = 6
|
||||||
def f(x):
|
def f(x):
|
||||||
|
@ -257,7 +279,7 @@ Backwards compatibility
|
||||||
|
|
||||||
There are two kinds of compatibility problems caused by nested
|
There are two kinds of compatibility problems caused by nested
|
||||||
scopes. In one case, code that behaved one way in earlier
|
scopes. In one case, code that behaved one way in earlier
|
||||||
versions, behaves differently because of nested scopes. In the
|
versions behaves differently because of nested scopes. In the
|
||||||
other cases, certain constructs interact badly with nested scopes
|
other cases, certain constructs interact badly with nested scopes
|
||||||
and will trigger SyntaxErrors at compile time.
|
and will trigger SyntaxErrors at compile time.
|
||||||
|
|
||||||
|
@ -285,9 +307,9 @@ Backwards compatibility
|
||||||
|
|
||||||
To address this problem, which is unlikely to occur often, a
|
To address this problem, which is unlikely to occur often, a
|
||||||
static analysis tool that detects affected code will be written.
|
static analysis tool that detects affected code will be written.
|
||||||
The detection problem is straightfoward.
|
The detection problem is straightforward.
|
||||||
|
|
||||||
The other compatibility problem is casued by the use of 'import *'
|
The other compatibility problem is caused by the use of 'import *'
|
||||||
and 'exec' in a function body, when that function contains a
|
and 'exec' in a function body, when that function contains a
|
||||||
nested scope and the contained scope has free variables. For
|
nested scope and the contained scope has free variables. For
|
||||||
example:
|
example:
|
||||||
|
@ -300,7 +322,7 @@ Backwards compatibility
|
||||||
...
|
...
|
||||||
|
|
||||||
At compile-time, the compiler cannot tell whether an exec that
|
At compile-time, the compiler cannot tell whether an exec that
|
||||||
operators on the local namespace or an import * will introduce
|
operates on the local namespace or an import * will introduce
|
||||||
name bindings that shadow the global y. Thus, it is not possible
|
name bindings that shadow the global y. Thus, it is not possible
|
||||||
to tell whether the reference to y in g() should refer to the
|
to tell whether the reference to y in g() should refer to the
|
||||||
global or to a local name in f().
|
global or to a local name in f().
|
||||||
|
@ -318,7 +340,7 @@ Backwards compatibility
|
||||||
above, the code would behave exactly as it did in earlier versions
|
above, the code would behave exactly as it did in earlier versions
|
||||||
of Python.
|
of Python.
|
||||||
|
|
||||||
Since each interpretation is problemtatic and the exact meaning
|
Since each interpretation is problematic and the exact meaning
|
||||||
ambiguous, the compiler raises an exception.
|
ambiguous, the compiler raises an exception.
|
||||||
|
|
||||||
A brief review of three Python projects (the standard library,
|
A brief review of three Python projects (the standard library,
|
||||||
|
@ -332,6 +354,12 @@ Backwards compatibility
|
||||||
language that in the reference manual that had never been
|
language that in the reference manual that had never been
|
||||||
enforced. These restrictions were relaxed following the release.)
|
enforced. These restrictions were relaxed following the release.)
|
||||||
|
|
||||||
|
Compatibility of C API
|
||||||
|
|
||||||
|
The implementation causes several Python C API functions to
|
||||||
|
change, including PyCode_New(). As a result, C extensions may
|
||||||
|
need to be updated to work correctly with Python 2.1.
|
||||||
|
|
||||||
locals() / vars()
|
locals() / vars()
|
||||||
|
|
||||||
These functions return a dictionary containing the current scope's
|
These functions return a dictionary containing the current scope's
|
||||||
|
@ -344,6 +372,49 @@ locals() / vars()
|
||||||
Under this proposal, it will not be possible to gain
|
Under this proposal, it will not be possible to gain
|
||||||
dictionary-style access to all visible scopes.
|
dictionary-style access to all visible scopes.
|
||||||
|
|
||||||
|
Warnings and Errors
|
||||||
|
|
||||||
|
The compiler will issue warnings in Python 2.1 to help identify
|
||||||
|
programs that may not compile or run correctly under future
|
||||||
|
versions of Python. Under Python 2.2 or Python 2.1 if the
|
||||||
|
nested_scopes future statement is used, which are collectively
|
||||||
|
referred to as "future semantics" in this section, the compiler
|
||||||
|
will issue SyntaxErrors in some cases.
|
||||||
|
|
||||||
|
The warnings typically apply when a function that contains a
|
||||||
|
nested function that has free variables. For example, if function
|
||||||
|
F contains a function G and G uses the builtin len(), then F is a
|
||||||
|
function that contains a nested function (G) with a free variable
|
||||||
|
(len). The label "free-in-nested" will be used to describe these
|
||||||
|
functions.
|
||||||
|
|
||||||
|
import * used in function scope
|
||||||
|
|
||||||
|
The language reference specifies that import * may only occur
|
||||||
|
in a module scope. (Sec. 6.11) The implementation of C
|
||||||
|
Python has supported import * at the function scope.
|
||||||
|
|
||||||
|
If import * is used in the body of a free-in-nested function,
|
||||||
|
the compiler will issue a warning. Under future semantics,
|
||||||
|
the compiler will raise a SyntaxError.
|
||||||
|
|
||||||
|
bare exec in function scope
|
||||||
|
|
||||||
|
The exec statement allows two optional expressions following
|
||||||
|
the keyword "in" that specify the namespaces used for locals
|
||||||
|
and globals. An exec statement that omits both of these
|
||||||
|
namespaces is a bare exec.
|
||||||
|
|
||||||
|
If a bare exec is used in the body of a free-in-nested
|
||||||
|
function, the compiler will issue a warning. Under future
|
||||||
|
semantics, the compiler will raise a SyntaxError.
|
||||||
|
|
||||||
|
local shadows global
|
||||||
|
|
||||||
|
If a free-in-nested function has a binding for a local
|
||||||
|
variable that (1) is used in a nested function and (2) is the
|
||||||
|
same as a global variable, the compiler will issue a warning.
|
||||||
|
|
||||||
Rebinding names in enclosing scopes
|
Rebinding names in enclosing scopes
|
||||||
|
|
||||||
There are technical issues that make it difficult to support
|
There are technical issues that make it difficult to support
|
||||||
|
@ -390,7 +461,17 @@ Implementation
|
||||||
or a free variable for a particular code object. A cell variable
|
or a free variable for a particular code object. A cell variable
|
||||||
is referenced by containing scopes; as a result, the function
|
is referenced by containing scopes; as a result, the function
|
||||||
where it is defined must allocate separate storage for it on each
|
where it is defined must allocate separate storage for it on each
|
||||||
invocation. A free variable is reference via a function's closure.
|
invocation. A free variable is referenced via a function's
|
||||||
|
closure.
|
||||||
|
|
||||||
|
The choice of free closures was made based on three factors.
|
||||||
|
First, nested functions are presumed to be used infrequently,
|
||||||
|
deeply nested (several levels of nesting) still less frequently.
|
||||||
|
Second, lookup of names in a nested scope should be fast.
|
||||||
|
Third, the use of nested scopes, particularly where a function
|
||||||
|
that access an enclosing scope is returned, should not prevent
|
||||||
|
unreferenced objects from being reclaimed by the garbage
|
||||||
|
collector.
|
||||||
|
|
||||||
XXX Much more to say here
|
XXX Much more to say here
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue