Convert PEPs 222, 224, 281, 284, 310 (#203)
This commit is contained in:
parent
0966f373b6
commit
c5881cf2b5
149
pep-0222.txt
149
pep-0222.txt
|
@ -5,106 +5,119 @@ Last-Modified: $Date$
|
|||
Author: A.M. Kuchling <amk@amk.ca>
|
||||
Status: Deferred
|
||||
Type: Standards Track
|
||||
Content-Type: text/x-rst
|
||||
Created: 18-Aug-2000
|
||||
Python-Version: 2.1
|
||||
Post-History: 22-Dec-2000
|
||||
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
This PEP proposes a set of enhancements to the CGI development
|
||||
facilities in the Python standard library. Enhancements might be
|
||||
new features, new modules for tasks such as cookie support, or
|
||||
removal of obsolete code.
|
||||
This PEP proposes a set of enhancements to the CGI development
|
||||
facilities in the Python standard library. Enhancements might be
|
||||
new features, new modules for tasks such as cookie support, or
|
||||
removal of obsolete code.
|
||||
|
||||
The original intent was to make improvements to Python 2.1.
|
||||
However, there seemed little interest from the Python community,
|
||||
and time was lacking, so this PEP has been deferred to some future
|
||||
Python release.
|
||||
The original intent was to make improvements to Python 2.1.
|
||||
However, there seemed little interest from the Python community,
|
||||
and time was lacking, so this PEP has been deferred to some future
|
||||
Python release.
|
||||
|
||||
|
||||
Open Issues
|
||||
===========
|
||||
|
||||
This section lists changes that have been suggested, but about
|
||||
which no firm decision has yet been made. In the final version of
|
||||
this PEP, this section should be empty, as all the changes should
|
||||
be classified as accepted or rejected.
|
||||
This section lists changes that have been suggested, but about
|
||||
which no firm decision has yet been made. In the final version of
|
||||
this PEP, this section should be empty, as all the changes should
|
||||
be classified as accepted or rejected.
|
||||
|
||||
cgi.py: We should not be told to create our own subclass just so
|
||||
we can handle file uploads. As a practical matter, I have yet to
|
||||
find the time to do this right, so I end up reading cgi.py's temp
|
||||
file into, at best, another file. Some of our legacy code actually
|
||||
reads it into a second temp file, then into a final destination!
|
||||
And even if we did, that would mean creating yet another object
|
||||
with its __init__ call and associated overhead.
|
||||
cgi.py: We should not be told to create our own subclass just so
|
||||
we can handle file uploads. As a practical matter, I have yet to
|
||||
find the time to do this right, so I end up reading cgi.py's temp
|
||||
file into, at best, another file. Some of our legacy code actually
|
||||
reads it into a second temp file, then into a final destination!
|
||||
And even if we did, that would mean creating yet another object
|
||||
with its ``__init__`` call and associated overhead.
|
||||
|
||||
cgi.py: Currently, query data with no `=' are ignored. Even if
|
||||
keep_blank_values is set, queries like `...?value=&...' are
|
||||
returned with blank values but queries like `...?value&...' are
|
||||
completely lost. It would be great if such data were made
|
||||
available through the FieldStorage interface, either as entries
|
||||
with None as values, or in a separate list.
|
||||
cgi.py: Currently, query data with no ``=`` are ignored. Even if
|
||||
keep_blank_values is set, queries like ``...?value=&...`` are
|
||||
returned with blank values but queries like ``...?value&...`` are
|
||||
completely lost. It would be great if such data were made
|
||||
available through the ``FieldStorage`` interface, either as entries
|
||||
with None as values, or in a separate list.
|
||||
|
||||
Utility function: build a query string from a list of 2-tuples
|
||||
Utility function: build a query string from a list of 2-tuples
|
||||
|
||||
Dictionary-related utility classes: NoKeyErrors (returns an empty
|
||||
string, never a KeyError), PartialStringSubstitution (returns
|
||||
the original key string, never a KeyError)
|
||||
Dictionary-related utility classes: ``NoKeyErrors`` (returns an empty
|
||||
string, never a ``KeyError``), ``PartialStringSubstitution`` (returns
|
||||
the original key string, never a ``KeyError``)
|
||||
|
||||
|
||||
|
||||
New Modules
|
||||
===========
|
||||
|
||||
This section lists details about entire new packages or modules
|
||||
that should be added to the Python standard library.
|
||||
This section lists details about entire new packages or modules
|
||||
that should be added to the Python standard library.
|
||||
|
||||
* fcgi.py : A new module adding support for the FastCGI protocol.
|
||||
Robin Dunn's code needs to be ported to Windows, though.
|
||||
|
||||
* fcgi.py : A new module adding support for the FastCGI protocol.
|
||||
Robin Dunn's code needs to be ported to Windows, though.
|
||||
|
||||
Major Changes to Existing Modules
|
||||
=================================
|
||||
|
||||
This section lists details of major changes to existing modules,
|
||||
whether in implementation or in interface. The changes in this
|
||||
section therefore carry greater degrees of risk, either in
|
||||
introducing bugs or a backward incompatibility.
|
||||
This section lists details of major changes to existing modules,
|
||||
whether in implementation or in interface. The changes in this
|
||||
section therefore carry greater degrees of risk, either in
|
||||
introducing bugs or a backward incompatibility.
|
||||
|
||||
The cgi.py module would be deprecated. (XXX A new module or
|
||||
package name hasn't been chosen yet: 'web'? 'cgilib'?)
|
||||
|
||||
The cgi.py module would be deprecated. (XXX A new module or
|
||||
package name hasn't been chosen yet: 'web'? 'cgilib'?)
|
||||
|
||||
Minor Changes to Existing Modules
|
||||
=================================
|
||||
|
||||
This section lists details of minor changes to existing modules.
|
||||
These changes should have relatively small implementations, and
|
||||
have little risk of introducing incompatibilities with previous
|
||||
versions.
|
||||
This section lists details of minor changes to existing modules.
|
||||
These changes should have relatively small implementations, and
|
||||
have little risk of introducing incompatibilities with previous
|
||||
versions.
|
||||
|
||||
|
||||
Rejected Changes
|
||||
================
|
||||
|
||||
The changes listed in this section were proposed for Python 2.1,
|
||||
but were rejected as unsuitable. For each rejected change, a
|
||||
rationale is given describing why the change was deemed
|
||||
inappropriate.
|
||||
The changes listed in this section were proposed for Python 2.1,
|
||||
but were rejected as unsuitable. For each rejected change, a
|
||||
rationale is given describing why the change was deemed
|
||||
inappropriate.
|
||||
|
||||
* An HTML generation module is not part of this PEP. Several such
|
||||
modules exist, ranging from HTMLgen's purely programming
|
||||
interface to ASP-inspired simple templating to DTML's complex
|
||||
templating. There's no indication of which templating module to
|
||||
enshrine in the standard library, and that probably means that
|
||||
no module should be so chosen.
|
||||
* An HTML generation module is not part of this PEP. Several such
|
||||
modules exist, ranging from HTMLgen's purely programming
|
||||
interface to ASP-inspired simple templating to DTML's complex
|
||||
templating. There's no indication of which templating module to
|
||||
enshrine in the standard library, and that probably means that
|
||||
no module should be so chosen.
|
||||
|
||||
* cgi.py: Allowing a combination of query data and POST data.
|
||||
This doesn't seem to be standard at all, and therefore is
|
||||
dubious practice.
|
||||
|
||||
* cgi.py: Allowing a combination of query data and POST data.
|
||||
This doesn't seem to be standard at all, and therefore is
|
||||
dubious practice.
|
||||
|
||||
Proposed Interface
|
||||
==================
|
||||
|
||||
XXX open issues: naming convention (studlycaps or
|
||||
underline-separated?); need to look at the cgi.parse*() functions
|
||||
and see if they can be simplified, too.
|
||||
XXX open issues: naming convention (studlycaps or
|
||||
underline-separated?); need to look at the ``cgi.parse*()`` functions
|
||||
and see if they can be simplified, too.
|
||||
|
||||
Parsing functions: carry over most of the parse* functions from
|
||||
cgi.py
|
||||
Parsing functions: carry over most of the ``parse*`` functions from
|
||||
cgi.py
|
||||
|
||||
::
|
||||
|
||||
# The Response class borrows most of its methods from Zope's
|
||||
# HTTPResponse class.
|
||||
|
@ -245,12 +258,14 @@ Proposed Interface
|
|||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
This document has been placed in the public domain.
|
||||
This document has been placed in the public domain.
|
||||
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
End:
|
||||
|
||||
..
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
End:
|
||||
|
|
337
pep-0224.txt
337
pep-0224.txt
|
@ -5,253 +5,272 @@ Last-Modified: $Date$
|
|||
Author: mal@lemburg.com (Marc-André Lemburg)
|
||||
Status: Rejected
|
||||
Type: Standards Track
|
||||
Content-Type: text/x-rst
|
||||
Created: 23-Aug-2000
|
||||
Python-Version: 2.1
|
||||
Post-History:
|
||||
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This PEP describes the "attribute docstring" proposal for Python
|
||||
2.0. This PEP tracks the status and ownership of this feature.
|
||||
It contains a description of the feature and outlines changes
|
||||
necessary to support the feature. The CVS revision history of
|
||||
this file contains the definitive historical record.
|
||||
This PEP describes the "attribute docstring" proposal for Python
|
||||
2.0. This PEP tracks the status and ownership of this feature.
|
||||
It contains a description of the feature and outlines changes
|
||||
necessary to support the feature. The CVS revision history of
|
||||
this file contains the definitive historical record.
|
||||
|
||||
|
||||
Rationale
|
||||
=========
|
||||
|
||||
This PEP proposes a small addition to the way Python currently
|
||||
handles docstrings embedded in Python code.
|
||||
This PEP proposes a small addition to the way Python currently
|
||||
handles docstrings embedded in Python code.
|
||||
|
||||
Python currently only handles the case of docstrings which appear
|
||||
directly after a class definition, a function definition or as
|
||||
first string literal in a module. The string literals are added
|
||||
to the objects in question under the __doc__ attribute and are
|
||||
from then on available for introspection tools which can extract
|
||||
the contained information for help, debugging and documentation
|
||||
purposes.
|
||||
Python currently only handles the case of docstrings which appear
|
||||
directly after a class definition, a function definition or as
|
||||
first string literal in a module. The string literals are added
|
||||
to the objects in question under the ``__doc__`` attribute and are
|
||||
from then on available for introspection tools which can extract
|
||||
the contained information for help, debugging and documentation
|
||||
purposes.
|
||||
|
||||
Docstrings appearing in locations other than the ones mentioned
|
||||
are simply ignored and don't result in any code generation.
|
||||
Docstrings appearing in locations other than the ones mentioned
|
||||
are simply ignored and don't result in any code generation.
|
||||
|
||||
Here is an example:
|
||||
Here is an example::
|
||||
|
||||
class C:
|
||||
"class C doc-string"
|
||||
class C:
|
||||
"class C doc-string"
|
||||
|
||||
a = 1
|
||||
"attribute C.a doc-string (1)"
|
||||
a = 1
|
||||
"attribute C.a doc-string (1)"
|
||||
|
||||
b = 2
|
||||
"attribute C.b doc-string (2)"
|
||||
b = 2
|
||||
"attribute C.b doc-string (2)"
|
||||
|
||||
The docstrings (1) and (2) are currently being ignored by the
|
||||
Python byte code compiler, but could obviously be put to good use
|
||||
for documenting the named assignments that precede them.
|
||||
The docstrings (1) and (2) are currently being ignored by the
|
||||
Python byte code compiler, but could obviously be put to good use
|
||||
for documenting the named assignments that precede them.
|
||||
|
||||
This PEP proposes to also make use of these cases by proposing
|
||||
semantics for adding their content to the objects in which they
|
||||
appear under new generated attribute names.
|
||||
This PEP proposes to also make use of these cases by proposing
|
||||
semantics for adding their content to the objects in which they
|
||||
appear under new generated attribute names.
|
||||
|
||||
The original idea behind this approach which also inspired the
|
||||
above example was to enable inline documentation of class
|
||||
attributes, which can currently only be documented in the class's
|
||||
docstring or using comments which are not available for
|
||||
introspection.
|
||||
The original idea behind this approach which also inspired the
|
||||
above example was to enable inline documentation of class
|
||||
attributes, which can currently only be documented in the class's
|
||||
docstring or using comments which are not available for
|
||||
introspection.
|
||||
|
||||
|
||||
Implementation
|
||||
==============
|
||||
|
||||
Docstrings are handled by the byte code compiler as expressions.
|
||||
The current implementation special cases the few locations
|
||||
mentioned above to make use of these expressions, but otherwise
|
||||
ignores the strings completely.
|
||||
Docstrings are handled by the byte code compiler as expressions.
|
||||
The current implementation special cases the few locations
|
||||
mentioned above to make use of these expressions, but otherwise
|
||||
ignores the strings completely.
|
||||
|
||||
To enable use of these docstrings for documenting named
|
||||
assignments (which is the natural way of defining e.g. class
|
||||
attributes), the compiler will have to keep track of the last
|
||||
assigned name and then use this name to assign the content of the
|
||||
docstring to an attribute of the containing object by means of
|
||||
storing it in as a constant which is then added to the object's
|
||||
namespace during object construction time.
|
||||
To enable use of these docstrings for documenting named
|
||||
assignments (which is the natural way of defining e.g. class
|
||||
attributes), the compiler will have to keep track of the last
|
||||
assigned name and then use this name to assign the content of the
|
||||
docstring to an attribute of the containing object by means of
|
||||
storing it in as a constant which is then added to the object's
|
||||
namespace during object construction time.
|
||||
|
||||
In order to preserve features like inheritance and hiding of
|
||||
Python's special attributes (ones with leading and trailing double
|
||||
underscores), a special name mangling has to be applied which
|
||||
uniquely identifies the docstring as belonging to the name
|
||||
assignment and allows finding the docstring later on by inspecting
|
||||
the namespace.
|
||||
In order to preserve features like inheritance and hiding of
|
||||
Python's special attributes (ones with leading and trailing double
|
||||
underscores), a special name mangling has to be applied which
|
||||
uniquely identifies the docstring as belonging to the name
|
||||
assignment and allows finding the docstring later on by inspecting
|
||||
the namespace.
|
||||
|
||||
The following name mangling scheme achieves all of the above:
|
||||
The following name mangling scheme achieves all of the above::
|
||||
|
||||
__doc_<attributename>__
|
||||
__doc_<attributename>__
|
||||
|
||||
To keep track of the last assigned name, the byte code compiler
|
||||
stores this name in a variable of the compiling structure. This
|
||||
variable defaults to NULL. When it sees a docstring, it then
|
||||
checks the variable and uses the name as basis for the above name
|
||||
mangling to produce an implicit assignment of the docstring to the
|
||||
mangled name. It then resets the variable to NULL to avoid
|
||||
duplicate assignments.
|
||||
To keep track of the last assigned name, the byte code compiler
|
||||
stores this name in a variable of the compiling structure. This
|
||||
variable defaults to NULL. When it sees a docstring, it then
|
||||
checks the variable and uses the name as basis for the above name
|
||||
mangling to produce an implicit assignment of the docstring to the
|
||||
mangled name. It then resets the variable to NULL to avoid
|
||||
duplicate assignments.
|
||||
|
||||
If the variable does not point to a name (i.e. is NULL), no
|
||||
assignments are made. These will continue to be ignored like
|
||||
before. All classical docstrings fall under this case, so no
|
||||
duplicate assignments are done.
|
||||
If the variable does not point to a name (i.e. is NULL), no
|
||||
assignments are made. These will continue to be ignored like
|
||||
before. All classical docstrings fall under this case, so no
|
||||
duplicate assignments are done.
|
||||
|
||||
In the above example this would result in the following new class
|
||||
attributes to be created:
|
||||
In the above example this would result in the following new class
|
||||
attributes to be created::
|
||||
|
||||
C.__doc_a__ == "attribute C.a doc-string (1)"
|
||||
C.__doc_b__ == "attribute C.b doc-string (2)"
|
||||
C.__doc_a__ == "attribute C.a doc-string (1)"
|
||||
C.__doc_b__ == "attribute C.b doc-string (2)"
|
||||
|
||||
A patch to the current CVS version of Python 2.0 which implements
|
||||
the above is available on SourceForge at [1].
|
||||
A patch to the current CVS version of Python 2.0 which implements
|
||||
the above is available on SourceForge at [1]_.
|
||||
|
||||
|
||||
Caveats of the Implementation
|
||||
=============================
|
||||
|
||||
Since the implementation does not reset the compiling structure
|
||||
variable when processing a non-expression, e.g. a function
|
||||
definition, the last assigned name remains active until either the
|
||||
next assignment or the next occurrence of a docstring.
|
||||
Since the implementation does not reset the compiling structure
|
||||
variable when processing a non-expression, e.g. a function
|
||||
definition, the last assigned name remains active until either the
|
||||
next assignment or the next occurrence of a docstring.
|
||||
|
||||
This can lead to cases where the docstring and assignment may be
|
||||
separated by other expressions:
|
||||
This can lead to cases where the docstring and assignment may be
|
||||
separated by other expressions::
|
||||
|
||||
class C:
|
||||
"C doc string"
|
||||
class C:
|
||||
"C doc string"
|
||||
|
||||
b = 2
|
||||
b = 2
|
||||
|
||||
def x(self):
|
||||
"C.x doc string"
|
||||
y = 3
|
||||
return 1
|
||||
def x(self):
|
||||
"C.x doc string"
|
||||
y = 3
|
||||
return 1
|
||||
|
||||
"b's doc string"
|
||||
"b's doc string"
|
||||
|
||||
Since the definition of method "x" currently does not reset the
|
||||
used assignment name variable, it is still valid when the compiler
|
||||
reaches the docstring "b's doc string" and thus assigns the string
|
||||
to __doc_b__.
|
||||
Since the definition of method "x" currently does not reset the
|
||||
used assignment name variable, it is still valid when the compiler
|
||||
reaches the docstring "b's doc string" and thus assigns the string
|
||||
to ``__doc_b__``.
|
||||
|
||||
A possible solution to this problem would be resetting the name
|
||||
variable for all non-expression nodes in the compiler.
|
||||
A possible solution to this problem would be resetting the name
|
||||
variable for all non-expression nodes in the compiler.
|
||||
|
||||
|
||||
Possible Problems
|
||||
=================
|
||||
|
||||
Even though highly unlikely, attribute docstrings could get
|
||||
accidentally concatenated to the attribute's value:
|
||||
Even though highly unlikely, attribute docstrings could get
|
||||
accidentally concatenated to the attribute's value::
|
||||
|
||||
class C:
|
||||
x = "text" \
|
||||
"x's docstring"
|
||||
class C:
|
||||
x = "text" \
|
||||
"x's docstring"
|
||||
|
||||
The trailing slash would cause the Python compiler to concatenate
|
||||
the attribute value and the docstring.
|
||||
The trailing slash would cause the Python compiler to concatenate
|
||||
the attribute value and the docstring.
|
||||
|
||||
A modern syntax highlighting editor would easily make this
|
||||
accident visible, though, and by simply inserting emtpy lines
|
||||
between the attribute definition and the docstring you can avoid
|
||||
the possible concatenation completely, so the problem is
|
||||
negligible.
|
||||
A modern syntax highlighting editor would easily make this
|
||||
accident visible, though, and by simply inserting emtpy lines
|
||||
between the attribute definition and the docstring you can avoid
|
||||
the possible concatenation completely, so the problem is
|
||||
negligible.
|
||||
|
||||
Another possible problem is that of using triple quoted strings as
|
||||
a way to uncomment parts of your code.
|
||||
Another possible problem is that of using triple quoted strings as
|
||||
a way to uncomment parts of your code.
|
||||
|
||||
If there happens to be an assignment just before the start of the
|
||||
comment string, then the compiler will treat the comment as
|
||||
docstring attribute and apply the above logic to it.
|
||||
If there happens to be an assignment just before the start of the
|
||||
comment string, then the compiler will treat the comment as
|
||||
docstring attribute and apply the above logic to it.
|
||||
|
||||
Besides generating a docstring for an otherwise undocumented
|
||||
attribute there is no breakage.
|
||||
Besides generating a docstring for an otherwise undocumented
|
||||
attribute there is no breakage.
|
||||
|
||||
|
||||
Comments from our BDFL
|
||||
======================
|
||||
|
||||
Early comments on the PEP from Guido:
|
||||
Early comments on the PEP from Guido:
|
||||
|
||||
I "kinda" like the idea of having attribute docstrings (meaning
|
||||
it's not of great importance to me) but there are two things I
|
||||
don't like in your current proposal:
|
||||
I "kinda" like the idea of having attribute docstrings (meaning
|
||||
it's not of great importance to me) but there are two things I
|
||||
don't like in your current proposal:
|
||||
|
||||
1. The syntax you propose is too ambiguous: as you say,
|
||||
stand-alone string literal are used for other purposes and could
|
||||
suddenly become attribute docstrings.
|
||||
1. The syntax you propose is too ambiguous: as you say,
|
||||
stand-alone string literal are used for other purposes and could
|
||||
suddenly become attribute docstrings.
|
||||
|
||||
2. I don't like the access method either (__doc_<attrname>__).
|
||||
2. I don't like the access method either (``__doc_<attrname>__``).
|
||||
|
||||
The author's reply:
|
||||
The author's reply
|
||||
|
||||
::
|
||||
|
||||
> 1. The syntax you propose is too ambiguous: as you say, stand-alone
|
||||
> string literal are used for other purposes and could suddenly
|
||||
> become attribute docstrings.
|
||||
|
||||
This can be fixed by introducing some extra checks in the
|
||||
compiler to reset the "doc attribute" flag in the compiler
|
||||
struct.
|
||||
|
||||
> 2. I don't like the access method either (__doc_<attrname>__).
|
||||
This can be fixed by introducing some extra checks in the
|
||||
compiler to reset the "doc attribute" flag in the compiler
|
||||
struct.
|
||||
|
||||
Any other name will do. It will only have to match these
|
||||
criteria:
|
||||
::
|
||||
|
||||
* must start with two underscores (to match __doc__)
|
||||
* must be extractable using some form of inspection (e.g. by using
|
||||
a naming convention which includes some fixed name part)
|
||||
* must be compatible with class inheritance (i.e. should be
|
||||
stored as attribute)
|
||||
> 2. I don't like the access method either (``__doc_<attrname>__``).
|
||||
|
||||
Later on in March, Guido pronounced on this PEP in March 2001 (on
|
||||
python-dev). Here are his reasons for rejection mentioned in
|
||||
private mail to the author of this PEP:
|
||||
Any other name will do. It will only have to match these
|
||||
criteria:
|
||||
|
||||
...
|
||||
* must start with two underscores (to match ``__doc__``)
|
||||
* must be extractable using some form of inspection (e.g. by using
|
||||
a naming convention which includes some fixed name part)
|
||||
* must be compatible with class inheritance (i.e. should be
|
||||
stored as attribute)
|
||||
|
||||
It might be useful, but I really hate the proposed syntax.
|
||||
Later on in March, Guido pronounced on this PEP in March 2001 (on
|
||||
python-dev). Here are his reasons for rejection mentioned in
|
||||
private mail to the author of this PEP:
|
||||
|
||||
a = 1
|
||||
"foo bar"
|
||||
b = 1
|
||||
...
|
||||
|
||||
I really have no way to know whether "foo bar" is a docstring
|
||||
for a or for b.
|
||||
It might be useful, but I really hate the proposed syntax.
|
||||
|
||||
...
|
||||
::
|
||||
|
||||
You can use this convention:
|
||||
a = 1
|
||||
"foo bar"
|
||||
b = 1
|
||||
|
||||
a = 1
|
||||
__doc_a__ = "doc string for a"
|
||||
I really have no way to know whether "foo bar" is a docstring
|
||||
for a or for b.
|
||||
|
||||
This makes it available at runtime.
|
||||
...
|
||||
|
||||
> Are you completely opposed to adding attribute documentation
|
||||
> to Python or is it just the way the implementation works ? I
|
||||
> find the syntax proposed in the PEP very intuitive and many
|
||||
> other users on c.l.p and in private emails have supported it
|
||||
> at the time I wrote the PEP.
|
||||
You can use this convention::
|
||||
|
||||
It's not the implementation, it's the syntax. It doesn't
|
||||
convey a clear enough coupling between the variable and the
|
||||
doc string.
|
||||
a = 1
|
||||
__doc_a__ = "doc string for a"
|
||||
|
||||
This makes it available at runtime.
|
||||
|
||||
::
|
||||
|
||||
> Are you completely opposed to adding attribute documentation
|
||||
> to Python or is it just the way the implementation works ? I
|
||||
> find the syntax proposed in the PEP very intuitive and many
|
||||
> other users on c.l.p and in private emails have supported it
|
||||
> at the time I wrote the PEP.
|
||||
|
||||
It's not the implementation, it's the syntax. It doesn't
|
||||
convey a clear enough coupling between the variable and the
|
||||
doc string.
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
This document has been placed in the Public Domain.
|
||||
This document has been placed in the Public Domain.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
[1] http://sourceforge.net/patch/?func=detailpatch&patch_id=101264&group_id=5470
|
||||
.. [1] http://sourceforge.net/patch/?func=detailpatch&patch_id=101264&group_id=5470
|
||||
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
End:
|
||||
|
||||
..
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
End:
|
||||
|
|
133
pep-0281.txt
133
pep-0281.txt
|
@ -5,56 +5,62 @@ Last-Modified: $Date$
|
|||
Author: magnus@hetland.org (Magnus Lie Hetland)
|
||||
Status: Rejected
|
||||
Type: Standards Track
|
||||
Content-Type: text/x-rst
|
||||
Created: 11-Feb-2002
|
||||
Python-Version: 2.3
|
||||
Post-History:
|
||||
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
This PEP describes yet another way of exposing the loop counter in
|
||||
for-loops. It basically proposes that the functionality of the
|
||||
function ``indices()`` from PEP 212 [1]_ be included in the existing
|
||||
functions ``range()`` and ``xrange()``.
|
||||
|
||||
This PEP describes yet another way of exposing the loop counter in
|
||||
for-loops. It basically proposes that the functionality of the
|
||||
function indices() from PEP 212 [1] be included in the existing
|
||||
functions range() and xrange().
|
||||
|
||||
Pronouncement
|
||||
=============
|
||||
|
||||
In commenting on PEP 279's enumerate() function, this PEP's author
|
||||
offered, "I'm quite happy to have it make PEP 281 obsolete."
|
||||
Subsequently, PEP 279 was accepted into Python 2.3.
|
||||
In commenting on PEP 279's ``enumerate()`` function, this PEP's author
|
||||
offered, "I'm quite happy to have it make PEP 281 obsolete."
|
||||
Subsequently, PEP 279 was accepted into Python 2.3.
|
||||
|
||||
On 17 June 2005, the BDFL concurred with it being obsolete and
|
||||
hereby rejected the PEP. For the record, he found some of the
|
||||
examples to somewhat jarring in appearance:
|
||||
On 17 June 2005, the BDFL concurred with it being obsolete and
|
||||
hereby rejected the PEP. For the record, he found some of the
|
||||
examples to somewhat jarring in appearance::
|
||||
|
||||
>>> range(range(5), range(10), range(2))
|
||||
[5, 7, 9]
|
||||
>>> range(range(5), range(10), range(2))
|
||||
[5, 7, 9]
|
||||
|
||||
|
||||
Motivation
|
||||
==========
|
||||
|
||||
It is often desirable to loop over the indices of a sequence. PEP
|
||||
212 describes several ways of doing this, including adding a
|
||||
built-in function called indices, conceptually defined as
|
||||
It is often desirable to loop over the indices of a sequence. PEP
|
||||
212 describes several ways of doing this, including adding a
|
||||
built-in function called indices, conceptually defined as::
|
||||
|
||||
def indices(sequence):
|
||||
return range(len(sequence))
|
||||
def indices(sequence):
|
||||
return range(len(sequence))
|
||||
|
||||
On the assumption that adding functionality to an existing built-in
|
||||
function may be less intrusive than adding a new built-in function,
|
||||
this PEP proposes adding this functionality to the existing
|
||||
functions range() and xrange().
|
||||
On the assumption that adding functionality to an existing built-in
|
||||
function may be less intrusive than adding a new built-in function,
|
||||
this PEP proposes adding this functionality to the existing
|
||||
functions ``range()`` and ``xrange()``.
|
||||
|
||||
|
||||
Specification
|
||||
=============
|
||||
|
||||
It is proposed that all three arguments to the built-in functions
|
||||
range() and xrange() are allowed to be objects with a length
|
||||
(i.e. objects implementing the __len__ method). If an argument
|
||||
cannot be interpreted as an integer (i.e. it has no __int__
|
||||
method), its length will be used instead.
|
||||
It is proposed that all three arguments to the built-in functions
|
||||
``range()`` and ``xrange()`` are allowed to be objects with a length
|
||||
(i.e. objects implementing the ``__len__`` method). If an argument
|
||||
cannot be interpreted as an integer (i.e. it has no ``__int__``
|
||||
method), its length will be used instead.
|
||||
|
||||
Examples:
|
||||
Examples::
|
||||
|
||||
>>> range(range(10))
|
||||
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
@ -74,18 +80,19 @@ Specification
|
|||
|
||||
|
||||
Alternatives
|
||||
============
|
||||
|
||||
A natural alternative to the above specification is allowing
|
||||
xrange() to access its arguments in a lazy manner. Thus, instead
|
||||
of using their length explicitly, xrange can return one index for
|
||||
each element of the stop argument until the end is reached. A
|
||||
similar lazy treatment makes little sense for the start and step
|
||||
arguments since their length must be calculated before iteration
|
||||
can begin. (Actually, the length of the step argument isn't needed
|
||||
until the second element is returned.)
|
||||
A natural alternative to the above specification is allowing
|
||||
``xrange()`` to access its arguments in a lazy manner. Thus, instead
|
||||
of using their length explicitly, ``xrange`` can return one index for
|
||||
each element of the stop argument until the end is reached. A
|
||||
similar lazy treatment makes little sense for the start and step
|
||||
arguments since their length must be calculated before iteration
|
||||
can begin. (Actually, the length of the step argument isn't needed
|
||||
until the second element is returned.)
|
||||
|
||||
A pseudo-implementation (using only the stop argument, and assuming
|
||||
that it is iterable) is:
|
||||
A pseudo-implementation (using only the stop argument, and assuming
|
||||
that it is iterable) is::
|
||||
|
||||
def xrange(stop):
|
||||
i = 0
|
||||
|
@ -93,26 +100,26 @@ Alternatives
|
|||
yield i
|
||||
i += 1
|
||||
|
||||
Testing whether to use int() or lazy iteration could be done by
|
||||
checking for an __iter__ attribute. (This example assumes the
|
||||
presence of generators, but could easily have been implemented as a
|
||||
plain iterator object.)
|
||||
Testing whether to use ``int()`` or lazy iteration could be done by
|
||||
checking for an ``__iter__`` attribute. (This example assumes the
|
||||
presence of generators, but could easily have been implemented as a
|
||||
plain iterator object.)
|
||||
|
||||
It may be questionable whether this feature is truly useful, since
|
||||
one would not be able to access the elements of the iterable object
|
||||
inside the for loop through indexing.
|
||||
It may be questionable whether this feature is truly useful, since
|
||||
one would not be able to access the elements of the iterable object
|
||||
inside the for loop through indexing.
|
||||
|
||||
Example:
|
||||
Example::
|
||||
|
||||
# Printing the numbers of the lines of a file:
|
||||
for num in range(file):
|
||||
print num # The line itself is not accessible
|
||||
|
||||
A more controversial alternative (to deal with this) would be to
|
||||
let range() behave like the function irange() of PEP 212 when
|
||||
supplied with a sequence.
|
||||
A more controversial alternative (to deal with this) would be to
|
||||
let ``range()`` behave like the function ``irange()`` of PEP 212 when
|
||||
supplied with a sequence.
|
||||
|
||||
Example:
|
||||
Example::
|
||||
|
||||
>>> range(5)
|
||||
[0, 1, 2, 3, 4]
|
||||
|
@ -121,27 +128,31 @@ Alternatives
|
|||
|
||||
|
||||
Backwards Compatibility
|
||||
=======================
|
||||
|
||||
The proposal could cause backwards incompatibilities if arguments
|
||||
are used which implement both __int__ and __len__ (or __iter__ in
|
||||
the case of lazy iteration with xrange). The author does not
|
||||
believe that this is a significant problem.
|
||||
The proposal could cause backwards incompatibilities if arguments
|
||||
are used which implement both ``__int__`` and ``__len__`` (or ``__iter__`` in
|
||||
the case of lazy iteration with ``xrange``). The author does not
|
||||
believe that this is a significant problem.
|
||||
|
||||
|
||||
References and Footnotes
|
||||
========================
|
||||
|
||||
[1] PEP 212, Loop Counter Iteration
|
||||
.. [1] PEP 212, Loop Counter Iteration
|
||||
http://www.python.org/dev/peps/pep-0212/
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
This document has been placed in the public domain.
|
||||
This document has been placed in the public domain.
|
||||
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
fill-column: 70
|
||||
End:
|
||||
|
||||
..
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
fill-column: 70
|
||||
End:
|
||||
|
|
381
pep-0284.txt
381
pep-0284.txt
|
@ -3,270 +3,285 @@ Title: Integer for-loops
|
|||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: David Eppstein <eppstein@ics.uci.edu>,
|
||||
Greg Ewing <greg.ewing@canterbury.ac.nz>
|
||||
Greg Ewing <greg.ewing@canterbury.ac.nz>
|
||||
Status: Rejected
|
||||
Type: Standards Track
|
||||
Content-Type: text/x-rst
|
||||
Created: 1-Mar-2002
|
||||
Python-Version: 2.3
|
||||
Post-History:
|
||||
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
This PEP proposes to simplify iteration over intervals of
|
||||
integers, by extending the range of expressions allowed after a
|
||||
"for" keyword to allow three-way comparisons such as
|
||||
This PEP proposes to simplify iteration over intervals of
|
||||
integers, by extending the range of expressions allowed after a
|
||||
"for" keyword to allow three-way comparisons such as::
|
||||
|
||||
for lower <= var < upper:
|
||||
for lower <= var < upper:
|
||||
|
||||
in place of the current
|
||||
in place of the current::
|
||||
|
||||
for item in list:
|
||||
for item in list:
|
||||
|
||||
syntax. The resulting loop or list iteration will loop over all
|
||||
values of var that make the comparison true, starting from the
|
||||
left endpoint of the given interval.
|
||||
|
||||
syntax. The resulting loop or list iteration will loop over all
|
||||
values of var that make the comparison true, starting from the
|
||||
left endpoint of the given interval.
|
||||
|
||||
Pronouncement
|
||||
=============
|
||||
|
||||
This PEP is rejected. There were a number of fixable issues with
|
||||
the proposal (see the fixups listed in Raymond Hettinger's
|
||||
python-dev post on 18 June 2005 [5]_). However, even with the fixups the
|
||||
proposal did not garner support. Specifically, Guido did not buy
|
||||
the premise that the ``range()`` format needed fixing, "The whole point
|
||||
(15 years ago) of ``range()`` was to *avoid* needing syntax to specify a
|
||||
loop over numbers. I think it's worked out well and there's nothing
|
||||
that needs to be fixed (except ``range()`` needs to become an iterator,
|
||||
which it will in Python 3.0)."
|
||||
|
||||
This PEP is rejected. There were a number of fixable issues with
|
||||
the proposal (see the fixups listed in Raymond Hettinger's
|
||||
python-dev post on 18 June 2005). However, even with the fixups the
|
||||
proposal did not garner support. Specifically, Guido did not buy
|
||||
the premise that the range() format needed fixing, "The whole point
|
||||
(15 years ago) of range() was to *avoid* needing syntax to specify a
|
||||
loop over numbers. I think it's worked out well and there's nothing
|
||||
that needs to be fixed (except range() needs to become an iterator,
|
||||
which it will in Python 3.0)."
|
||||
|
||||
Rationale
|
||||
=========
|
||||
|
||||
One of the most common uses of for-loops in Python is to iterate
|
||||
over an interval of integers. Python provides functions range()
|
||||
and xrange() to generate lists and iterators for such intervals,
|
||||
which work best for the most frequent case: half-open intervals
|
||||
increasing from zero. However, the range() syntax is more awkward
|
||||
for open or closed intervals, and lacks symmetry when reversing
|
||||
the order of iteration. In addition, the call to an unfamiliar
|
||||
function makes it difficult for newcomers to Python to understand
|
||||
code that uses range() or xrange().
|
||||
One of the most common uses of for-loops in Python is to iterate
|
||||
over an interval of integers. Python provides functions ``range()``
|
||||
and ``xrange()`` to generate lists and iterators for such intervals,
|
||||
which work best for the most frequent case: half-open intervals
|
||||
increasing from zero. However, the ``range()`` syntax is more awkward
|
||||
for open or closed intervals, and lacks symmetry when reversing
|
||||
the order of iteration. In addition, the call to an unfamiliar
|
||||
function makes it difficult for newcomers to Python to understand
|
||||
code that uses ``range()`` or ``xrange()``.
|
||||
|
||||
The perceived lack of a natural, intuitive integer iteration
|
||||
syntax has led to heated debate on python-list, and spawned at
|
||||
least four PEPs before this one. PEP 204 [1] (rejected) proposed
|
||||
to re-use Python's slice syntax for integer ranges, leading to a
|
||||
terser syntax but not solving the readability problem of
|
||||
multi-argument range(). PEP 212 [2] (deferred) proposed several
|
||||
syntaxes for directly converting a list to a sequence of integer
|
||||
indices, in place of the current idiom
|
||||
The perceived lack of a natural, intuitive integer iteration
|
||||
syntax has led to heated debate on python-list, and spawned at
|
||||
least four PEPs before this one. PEP 204 [1]_ (rejected) proposed
|
||||
to re-use Python's slice syntax for integer ranges, leading to a
|
||||
terser syntax but not solving the readability problem of
|
||||
multi-argument ``range()``. PEP 212 [2]_ (deferred) proposed several
|
||||
syntaxes for directly converting a list to a sequence of integer
|
||||
indices, in place of the current idiom::
|
||||
|
||||
range(len(list))
|
||||
range(len(list))
|
||||
|
||||
for such conversion, and PEP 281 [3] proposes to simplify the same
|
||||
idiom by allowing it to be written as
|
||||
for such conversion, and PEP 281 [3]_ proposes to simplify the same
|
||||
idiom by allowing it to be written as::
|
||||
|
||||
range(list).
|
||||
range(list).
|
||||
|
||||
PEP 276 [4] proposes to allow automatic conversion of integers to
|
||||
iterators, simplifying the most common half-open case but not
|
||||
addressing the complexities of other types of interval.
|
||||
Additional alternatives have been discussed on python-list.
|
||||
PEP 276 [4]_ proposes to allow automatic conversion of integers to
|
||||
iterators, simplifying the most common half-open case but not
|
||||
addressing the complexities of other types of interval.
|
||||
Additional alternatives have been discussed on python-list.
|
||||
|
||||
The solution described here is to allow a three-way comparison
|
||||
after a "for" keyword, both in the context of a for-loop and of a
|
||||
list comprehension:
|
||||
The solution described here is to allow a three-way comparison
|
||||
after a "for" keyword, both in the context of a for-loop and of a
|
||||
list comprehension::
|
||||
|
||||
for lower <= var < upper:
|
||||
for lower <= var < upper:
|
||||
|
||||
This would cause iteration over an interval of consecutive
|
||||
integers, beginning at the left bound in the comparison and ending
|
||||
at the right bound. The exact comparison operations used would
|
||||
determine whether the interval is open or closed at either end and
|
||||
whether the integers are considered in ascending or descending
|
||||
order.
|
||||
This would cause iteration over an interval of consecutive
|
||||
integers, beginning at the left bound in the comparison and ending
|
||||
at the right bound. The exact comparison operations used would
|
||||
determine whether the interval is open or closed at either end and
|
||||
whether the integers are considered in ascending or descending
|
||||
order.
|
||||
|
||||
This syntax closely matches standard mathematical notation, so is
|
||||
likely to be more familiar to Python novices than the current
|
||||
range() syntax. Open and closed interval endpoints are equally
|
||||
easy to express, and the reversal of an integer interval can be
|
||||
formed simply by swapping the two endpoints and reversing the
|
||||
comparisons. In addition, the semantics of such a loop would
|
||||
closely resemble one way of interpreting the existing Python
|
||||
for-loops:
|
||||
This syntax closely matches standard mathematical notation, so is
|
||||
likely to be more familiar to Python novices than the current
|
||||
``range()`` syntax. Open and closed interval endpoints are equally
|
||||
easy to express, and the reversal of an integer interval can be
|
||||
formed simply by swapping the two endpoints and reversing the
|
||||
comparisons. In addition, the semantics of such a loop would
|
||||
closely resemble one way of interpreting the existing Python
|
||||
for-loops::
|
||||
|
||||
for item in list
|
||||
for item in list
|
||||
|
||||
iterates over exactly those values of item that cause the
|
||||
expression
|
||||
iterates over exactly those values of item that cause the
|
||||
expression::
|
||||
|
||||
item in list
|
||||
item in list
|
||||
|
||||
to be true. Similarly, the new format
|
||||
to be true. Similarly, the new format::
|
||||
|
||||
for lower <= var < upper:
|
||||
for lower <= var < upper:
|
||||
|
||||
would iterate over exactly those integer values of var that cause
|
||||
the expression
|
||||
would iterate over exactly those integer values of var that cause
|
||||
the expression::
|
||||
|
||||
lower <= var < upper
|
||||
lower <= var < upper
|
||||
|
||||
to be true.
|
||||
to be true.
|
||||
|
||||
|
||||
Specification
|
||||
=============
|
||||
|
||||
We propose to extend the syntax of a for statement, currently
|
||||
We propose to extend the syntax of a for statement, currently::
|
||||
|
||||
for_stmt: "for" target_list "in" expression_list ":" suite
|
||||
["else" ":" suite]
|
||||
for_stmt: "for" target_list "in" expression_list ":" suite
|
||||
["else" ":" suite]
|
||||
|
||||
as described below:
|
||||
as described below::
|
||||
|
||||
for_stmt: "for" for_test ":" suite ["else" ":" suite]
|
||||
for_test: target_list "in" expression_list |
|
||||
or_expr less_comp or_expr less_comp or_expr |
|
||||
or_expr greater_comp or_expr greater_comp or_expr
|
||||
less_comp: "<" | "<="
|
||||
greater_comp: ">" | ">="
|
||||
for_stmt: "for" for_test ":" suite ["else" ":" suite]
|
||||
for_test: target_list "in" expression_list |
|
||||
or_expr less_comp or_expr less_comp or_expr |
|
||||
or_expr greater_comp or_expr greater_comp or_expr
|
||||
less_comp: "<" | "<="
|
||||
greater_comp: ">" | ">="
|
||||
|
||||
Similarly, we propose to extend the syntax of list comprehensions,
|
||||
currently
|
||||
Similarly, we propose to extend the syntax of list comprehensions,
|
||||
currently::
|
||||
|
||||
list_for: "for" expression_list "in" testlist [list_iter]
|
||||
list_for: "for" expression_list "in" testlist [list_iter]
|
||||
|
||||
by replacing it with:
|
||||
by replacing it with::
|
||||
|
||||
list_for: "for" for_test [list_iter]
|
||||
list_for: "for" for_test [list_iter]
|
||||
|
||||
In all cases the expression formed by for_test would be subject to
|
||||
the same precedence rules as comparisons in expressions. The two
|
||||
comp_operators in a for_test must be required to be both of
|
||||
similar types, unlike chained comparisons in expressions which do
|
||||
not have such a restriction.
|
||||
In all cases the expression formed by for_test would be subject to
|
||||
the same precedence rules as comparisons in expressions. The two
|
||||
comp_operators in a for_test must be required to be both of
|
||||
similar types, unlike chained comparisons in expressions which do
|
||||
not have such a restriction.
|
||||
|
||||
We refer to the two or_expr's occurring on the left and right
|
||||
sides of the for-loop syntax as the bounds of the loop, and the
|
||||
middle or_expr as the variable of the loop. When a for-loop using
|
||||
the new syntax is executed, the expressions for both bounds will
|
||||
be evaluated, and an iterator object created that iterates through
|
||||
all integers between the two bounds according to the comparison
|
||||
operations used. The iterator will begin with an integer equal or
|
||||
near to the left bound, and then step through the remaining
|
||||
integers with a step size of +1 or -1 if the comparison operation
|
||||
is in the set described by less_comp or greater_comp respectively.
|
||||
The execution will then proceed as if the expression had been
|
||||
We refer to the two or_expr's occurring on the left and right
|
||||
sides of the for-loop syntax as the bounds of the loop, and the
|
||||
middle or_expr as the variable of the loop. When a for-loop using
|
||||
the new syntax is executed, the expressions for both bounds will
|
||||
be evaluated, and an iterator object created that iterates through
|
||||
all integers between the two bounds according to the comparison
|
||||
operations used. The iterator will begin with an integer equal or
|
||||
near to the left bound, and then step through the remaining
|
||||
integers with a step size of +1 or -1 if the comparison operation
|
||||
is in the set described by less_comp or greater_comp respectively.
|
||||
The execution will then proceed as if the expression had been::
|
||||
|
||||
for variable in iterator
|
||||
for variable in iterator
|
||||
|
||||
where "variable" refers to the variable of the loop and "iterator"
|
||||
refers to the iterator created for the given integer interval.
|
||||
where "variable" refers to the variable of the loop and "iterator"
|
||||
refers to the iterator created for the given integer interval.
|
||||
|
||||
The values taken by the loop variable in an integer for-loop may
|
||||
be either plain integers or long integers, according to the
|
||||
magnitude of the bounds. Both bounds of an integer for-loop must
|
||||
evaluate to a real numeric type (integer, long, or float). Any
|
||||
other value will cause the for-loop statement to raise a TypeError
|
||||
exception.
|
||||
The values taken by the loop variable in an integer for-loop may
|
||||
be either plain integers or long integers, according to the
|
||||
magnitude of the bounds. Both bounds of an integer for-loop must
|
||||
evaluate to a real numeric type (integer, long, or float). Any
|
||||
other value will cause the for-loop statement to raise a ``TypeError``
|
||||
exception.
|
||||
|
||||
|
||||
Issues
|
||||
======
|
||||
|
||||
The following issues were raised in discussion of this and related
|
||||
proposals on the Python list.
|
||||
The following issues were raised in discussion of this and related
|
||||
proposals on the Python list.
|
||||
|
||||
- Should the right bound be evaluated once, or every time through
|
||||
the loop? Clearly, it only makes sense to evaluate the left
|
||||
bound once. For reasons of consistency and efficiency, we have
|
||||
chosen the same convention for the right bound.
|
||||
- Should the right bound be evaluated once, or every time through
|
||||
the loop? Clearly, it only makes sense to evaluate the left
|
||||
bound once. For reasons of consistency and efficiency, we have
|
||||
chosen the same convention for the right bound.
|
||||
|
||||
- Although the new syntax considerably simplifies integer
|
||||
for-loops, list comprehensions using the new syntax are not as
|
||||
simple. We feel that this is appropriate since for-loops are
|
||||
more frequent than comprehensions.
|
||||
- Although the new syntax considerably simplifies integer
|
||||
for-loops, list comprehensions using the new syntax are not as
|
||||
simple. We feel that this is appropriate since for-loops are
|
||||
more frequent than comprehensions.
|
||||
|
||||
- The proposal does not allow access to integer iterator objects
|
||||
such as would be created by xrange. True, but we see this as a
|
||||
shortcoming in the general list-comprehension syntax, beyond the
|
||||
scope of this proposal. In addition, xrange() will still be
|
||||
available.
|
||||
- The proposal does not allow access to integer iterator objects
|
||||
such as would be created by ``xrange``. True, but we see this as a
|
||||
shortcoming in the general list-comprehension syntax, beyond the
|
||||
scope of this proposal. In addition, ``xrange()`` will still be
|
||||
available.
|
||||
|
||||
- The proposal does not allow increments other than 1 and -1.
|
||||
More general arithmetic progressions would need to be created by
|
||||
range() or xrange(), or by a list comprehension syntax such as
|
||||
- The proposal does not allow increments other than 1 and -1.
|
||||
More general arithmetic progressions would need to be created by
|
||||
``range()`` or ``xrange()``, or by a list comprehension syntax such as::
|
||||
|
||||
[2*x for 0 <= x <= 100]
|
||||
[2*x for 0 <= x <= 100]
|
||||
|
||||
- The position of the loop variable in the middle of a three-way
|
||||
comparison is not as apparent as the variable in the present
|
||||
- The position of the loop variable in the middle of a three-way
|
||||
comparison is not as apparent as the variable in the present::
|
||||
|
||||
for item in list
|
||||
for item in list
|
||||
|
||||
syntax, leading to a possible loss of readability. We feel that
|
||||
this loss is outweighed by the increase in readability from a
|
||||
natural integer iteration syntax.
|
||||
syntax, leading to a possible loss of readability. We feel that
|
||||
this loss is outweighed by the increase in readability from a
|
||||
natural integer iteration syntax.
|
||||
|
||||
- To some extent, this PEP addresses the same issues as PEP 276
|
||||
[4]. We feel that the two PEPs are not in conflict since PEP
|
||||
276 is primarily concerned with half-open ranges starting in 0
|
||||
(the easy case of range()) while this PEP is primarily concerned
|
||||
with simplifying all other cases. However, if this PEP is
|
||||
approved, its new simpler syntax for integer loops could to some
|
||||
extent reduce the motivation for PEP 276.
|
||||
- To some extent, this PEP addresses the same issues as PEP 276
|
||||
[4]_. We feel that the two PEPs are not in conflict since PEP
|
||||
276 is primarily concerned with half-open ranges starting in 0
|
||||
(the easy case of ``range()``) while this PEP is primarily concerned
|
||||
with simplifying all other cases. However, if this PEP is
|
||||
approved, its new simpler syntax for integer loops could to some
|
||||
extent reduce the motivation for PEP 276.
|
||||
|
||||
- It is not clear whether it makes sense to allow floating point
|
||||
bounds for an integer loop: if a float represents an inexact
|
||||
value, how can it be used to determine an exact sequence of
|
||||
integers? On the other hand, disallowing float bounds would
|
||||
make it difficult to use floor() and ceiling() in integer
|
||||
for-loops, as it is difficult to use them now with range(). We
|
||||
have erred on the side of flexibility, but this may lead to some
|
||||
implementation difficulties in determining the smallest and
|
||||
largest integer values that would cause a given comparison to be
|
||||
true.
|
||||
- It is not clear whether it makes sense to allow floating point
|
||||
bounds for an integer loop: if a float represents an inexact
|
||||
value, how can it be used to determine an exact sequence of
|
||||
integers? On the other hand, disallowing float bounds would
|
||||
make it difficult to use ``floor()`` and ``ceiling()`` in integer
|
||||
for-loops, as it is difficult to use them now with ``range()``. We
|
||||
have erred on the side of flexibility, but this may lead to some
|
||||
implementation difficulties in determining the smallest and
|
||||
largest integer values that would cause a given comparison to be
|
||||
true.
|
||||
|
||||
- Should types other than int, long, and float be allowed as
|
||||
bounds? Another choice would be to convert all bounds to
|
||||
integers by int(), and allow as bounds anything that can be so
|
||||
converted instead of just floats. However, this would change
|
||||
the semantics: 0.3 <= x is not the same as int(0.3) <= x, and it
|
||||
would be confusing for a loop with 0.3 as lower bound to start
|
||||
at zero. Also, in general int(f) can be very far from f.
|
||||
- Should types other than int, long, and float be allowed as
|
||||
bounds? Another choice would be to convert all bounds to
|
||||
integers by ``int()``, and allow as bounds anything that can be so
|
||||
converted instead of just floats. However, this would change
|
||||
the semantics: ``0.3 <= x`` is not the same as ``int(0.3) <= x``, and it
|
||||
would be confusing for a loop with 0.3 as lower bound to start
|
||||
at zero. Also, in general ``int(f)`` can be very far from ``f``.
|
||||
|
||||
|
||||
Implementation
|
||||
==============
|
||||
|
||||
An implementation is not available at this time. Implementation
|
||||
is not expected to pose any great difficulties: the new syntax
|
||||
could, if necessary, be recognized by parsing a general expression
|
||||
after each "for" keyword and testing whether the top level
|
||||
operation of the expression is "in" or a three-way comparison.
|
||||
The Python compiler would convert any instance of the new syntax
|
||||
into a loop over the items in a special iterator object.
|
||||
An implementation is not available at this time. Implementation
|
||||
is not expected to pose any great difficulties: the new syntax
|
||||
could, if necessary, be recognized by parsing a general expression
|
||||
after each "for" keyword and testing whether the top level
|
||||
operation of the expression is "in" or a three-way comparison.
|
||||
The Python compiler would convert any instance of the new syntax
|
||||
into a loop over the items in a special iterator object.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
[1] PEP 204, Range Literals
|
||||
http://www.python.org/dev/peps/pep-0204/
|
||||
.. [1] PEP 204, Range Literals
|
||||
http://www.python.org/dev/peps/pep-0204/
|
||||
|
||||
[2] PEP 212, Loop Counter Iteration
|
||||
http://www.python.org/dev/peps/pep-0212/
|
||||
.. [2] PEP 212, Loop Counter Iteration
|
||||
http://www.python.org/dev/peps/pep-0212/
|
||||
|
||||
[3] PEP 281, Loop Counter Iteration with range and xrange
|
||||
http://www.python.org/dev/peps/pep-0281/
|
||||
.. [3] PEP 281, Loop Counter Iteration with range and xrange
|
||||
http://www.python.org/dev/peps/pep-0281/
|
||||
|
||||
[4] PEP 276, Simple Iterator for ints
|
||||
http://www.python.org/dev/peps/pep-0276/
|
||||
.. [4] PEP 276, Simple Iterator for ints
|
||||
http://www.python.org/dev/peps/pep-0276/
|
||||
|
||||
.. [5] Raymond Hettinger, Propose updating PEP 284 -- Integer for-loops
|
||||
https://mail.python.org/pipermail/python-dev/2005-June/054316.html
|
||||
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
This document has been placed in the public domain.
|
||||
This document has been placed in the public domain.
|
||||
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
fill-column: 70
|
||||
End:
|
||||
|
||||
..
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
fill-column: 70
|
||||
End:
|
||||
|
|
306
pep-0310.txt
306
pep-0310.txt
|
@ -3,241 +3,259 @@ Title: Reliable Acquisition/Release Pairs
|
|||
Version: $Revision$
|
||||
Last-Modified: $Date$
|
||||
Author: Michael Hudson <mwh@python.net>,
|
||||
Paul Moore <p.f.moore@gmail.com>
|
||||
Paul Moore <p.f.moore@gmail.com>
|
||||
Status: Rejected
|
||||
Type: Standards Track
|
||||
Content-Type: text/plain
|
||||
Content-Type: text/x-rst
|
||||
Created: 18-Dec-2002
|
||||
Python-Version: 2.4
|
||||
Post-History:
|
||||
|
||||
|
||||
Abstract
|
||||
========
|
||||
|
||||
It would be nice to have a less typing-intense way of writing:
|
||||
It would be nice to have a less typing-intense way of writing::
|
||||
|
||||
the_lock.acquire()
|
||||
try:
|
||||
....
|
||||
finally:
|
||||
the_lock.release()
|
||||
the_lock.acquire()
|
||||
try:
|
||||
....
|
||||
finally:
|
||||
the_lock.release()
|
||||
|
||||
This PEP proposes a piece of syntax (a 'with' block) and a
|
||||
"small-i" interface that generalizes the above.
|
||||
|
||||
This PEP proposes a piece of syntax (a 'with' block) and a
|
||||
"small-i" interface that generalizes the above.
|
||||
|
||||
Pronouncement
|
||||
=============
|
||||
|
||||
This PEP is rejected in favor of PEP 343.
|
||||
|
||||
This PEP is rejected in favor of PEP 343.
|
||||
|
||||
Rationale
|
||||
=========
|
||||
|
||||
One of the advantages of Python's exception handling philosophy is
|
||||
that it makes it harder to do the "wrong" thing (e.g. failing to
|
||||
check the return value of some system call). Currently, this does
|
||||
not apply to resource cleanup. The current syntax for acquisition
|
||||
and release of a resource (for example, a lock) is
|
||||
One of the advantages of Python's exception handling philosophy is
|
||||
that it makes it harder to do the "wrong" thing (e.g. failing to
|
||||
check the return value of some system call). Currently, this does
|
||||
not apply to resource cleanup. The current syntax for acquisition
|
||||
and release of a resource (for example, a lock) is::
|
||||
|
||||
the_lock.acquire()
|
||||
try:
|
||||
....
|
||||
finally:
|
||||
the_lock.release()
|
||||
the_lock.acquire()
|
||||
try:
|
||||
....
|
||||
finally:
|
||||
the_lock.release()
|
||||
|
||||
This syntax separates the acquisition and release by a (possibly
|
||||
large) block of code, which makes it difficult to confirm "at a
|
||||
glance" that the code manages the resource correctly. Another
|
||||
common error is to code the "acquire" call within the try block,
|
||||
which incorrectly releases the lock if the acquire fails.
|
||||
This syntax separates the acquisition and release by a (possibly
|
||||
large) block of code, which makes it difficult to confirm "at a
|
||||
glance" that the code manages the resource correctly. Another
|
||||
common error is to code the "acquire" call within the try block,
|
||||
which incorrectly releases the lock if the acquire fails.
|
||||
|
||||
|
||||
Basic Syntax and Semantics
|
||||
==========================
|
||||
|
||||
The syntax of a 'with' statement is as follows::
|
||||
The syntax of a 'with' statement is as follows::
|
||||
|
||||
'with' [ var '=' ] expr ':'
|
||||
suite
|
||||
suite
|
||||
|
||||
This statement is defined as being equivalent to the following
|
||||
sequence of statements:
|
||||
This statement is defined as being equivalent to the following
|
||||
sequence of statements::
|
||||
|
||||
var = expr
|
||||
|
||||
if hasattr(var, "__enter__"):
|
||||
var.__enter__()
|
||||
var.__enter__()
|
||||
|
||||
try:
|
||||
suite
|
||||
suite
|
||||
|
||||
finally:
|
||||
var.__exit__()
|
||||
var.__exit__()
|
||||
|
||||
(The presence of an __exit__ method is *not* checked like that of
|
||||
__enter__ to ensure that using inappropriate objects in with:
|
||||
statements gives an error).
|
||||
(The presence of an ``__exit__`` method is *not* checked like that of
|
||||
``__enter__`` to ensure that using inappropriate objects in with:
|
||||
statements gives an error).
|
||||
|
||||
If the variable is omitted, an unnamed object is allocated on the
|
||||
stack. In that case, the suite has no access to the unnamed object.
|
||||
If the variable is omitted, an unnamed object is allocated on the
|
||||
stack. In that case, the suite has no access to the unnamed object.
|
||||
|
||||
|
||||
Possible Extensions
|
||||
===================
|
||||
|
||||
A number of potential extensions to the basic syntax have been
|
||||
discussed on the Python Developers list. None of these extensions
|
||||
are included in the solution proposed by this PEP. In many cases,
|
||||
the arguments are nearly equally strong in both directions. In
|
||||
such cases, the PEP has always chosen simplicity, simply because
|
||||
where extra power is needed, the existing try block is available.
|
||||
A number of potential extensions to the basic syntax have been
|
||||
discussed on the Python Developers list. None of these extensions
|
||||
are included in the solution proposed by this PEP. In many cases,
|
||||
the arguments are nearly equally strong in both directions. In
|
||||
such cases, the PEP has always chosen simplicity, simply because
|
||||
where extra power is needed, the existing try block is available.
|
||||
|
||||
Multiple expressions
|
||||
Multiple expressions
|
||||
--------------------
|
||||
|
||||
One proposal was for allowing multiple expressions within one
|
||||
'with' statement. The __enter__ methods would be called left to
|
||||
right, and the __exit__ methods right to left. The advantage of
|
||||
doing so is that where more than one resource is being managed,
|
||||
nested 'with' statements will result in code drifting towards the
|
||||
right margin. The solution to this problem is the same as for any
|
||||
other deep nesting - factor out some of the code into a separate
|
||||
function. Furthermore, the question of what happens if one of the
|
||||
__exit__ methods raises an exception (should the other __exit__
|
||||
methods be called?) needs to be addressed.
|
||||
One proposal was for allowing multiple expressions within one
|
||||
'with' statement. The ``__enter__`` methods would be called left to
|
||||
right, and the ``__exit__`` methods right to left. The advantage of
|
||||
doing so is that where more than one resource is being managed,
|
||||
nested 'with' statements will result in code drifting towards the
|
||||
right margin. The solution to this problem is the same as for any
|
||||
other deep nesting - factor out some of the code into a separate
|
||||
function. Furthermore, the question of what happens if one of the
|
||||
``__exit__`` methods raises an exception (should the other ``__exit__``
|
||||
methods be called?) needs to be addressed.
|
||||
|
||||
Exception handling
|
||||
Exception handling
|
||||
------------------
|
||||
|
||||
An extension to the protocol to include an optional __except__
|
||||
handler, which is called when an exception is raised, and which
|
||||
can handle or re-raise the exception, has been suggested. It is
|
||||
not at all clear that the semantics of this extension can be made
|
||||
precise and understandable. For example, should the equivalent
|
||||
code be try ... except ... else if an exception handler is
|
||||
defined, and try ... finally if not? How can this be determined
|
||||
at compile time, in general? The alternative is to define the
|
||||
code as expanding to a try ... except inside a try ... finally.
|
||||
But this may not do the right thing in real life.
|
||||
An extension to the protocol to include an optional ``__except__``
|
||||
handler, which is called when an exception is raised, and which
|
||||
can handle or re-raise the exception, has been suggested. It is
|
||||
not at all clear that the semantics of this extension can be made
|
||||
precise and understandable. For example, should the equivalent
|
||||
code be ``try ... except ... else`` if an exception handler is
|
||||
defined, and ``try ... finally`` if not? How can this be determined
|
||||
at compile time, in general? The alternative is to define the
|
||||
code as expanding to a ``try ... except`` inside a ``try ... finally``.
|
||||
But this may not do the right thing in real life.
|
||||
|
||||
The only use case identified for exception handling is with
|
||||
transactional processing (commit on a clean finish, and rollback
|
||||
on an exception). This is probably just as easy to handle with a
|
||||
conventional try ... except ... else block, and so the PEP does
|
||||
not include any support for exception handlers.
|
||||
The only use case identified for exception handling is with
|
||||
transactional processing (commit on a clean finish, and rollback
|
||||
on an exception). This is probably just as easy to handle with a
|
||||
conventional ``try ... except ... else`` block, and so the PEP does
|
||||
not include any support for exception handlers.
|
||||
|
||||
|
||||
Implementation Notes
|
||||
====================
|
||||
|
||||
There is a potential race condition in the code specified as
|
||||
equivalent to the with statement. For example, if a
|
||||
KeyboardInterrupt exception is raised between the completion of
|
||||
the __enter__ method call and the start of the try block, the
|
||||
__exit__ method will not be called. This can lead to resource
|
||||
leaks, or to deadlocks. [XXX Guido has stated that he cares about
|
||||
this sort of race condition, and intends to write some C magic to
|
||||
handle them. The implementation of the 'with' statement should
|
||||
copy this.]
|
||||
There is a potential race condition in the code specified as
|
||||
equivalent to the with statement. For example, if a
|
||||
``KeyboardInterrupt`` exception is raised between the completion of
|
||||
the ``__enter__`` method call and the start of the try block, the
|
||||
``__exit__`` method will not be called. This can lead to resource
|
||||
leaks, or to deadlocks. [XXX Guido has stated that he cares about
|
||||
this sort of race condition, and intends to write some C magic to
|
||||
handle them. The implementation of the 'with' statement should
|
||||
copy this.]
|
||||
|
||||
|
||||
Open Issues
|
||||
===========
|
||||
|
||||
Should existing classes (for example, file-like objects and locks)
|
||||
gain appropriate __enter__ and __exit__ methods? The obvious
|
||||
reason in favour is convenience (no adapter needed). The argument
|
||||
against is that if built-in files have this but (say) StringIO
|
||||
does not, then code that uses "with" on a file object can't be
|
||||
reused with a StringIO object. So __exit__ = close becomes a part
|
||||
of the "file-like object" protocol, which user-defined classes may
|
||||
need to support.
|
||||
Should existing classes (for example, file-like objects and locks)
|
||||
gain appropriate ``__enter__`` and ``__exit__`` methods? The obvious
|
||||
reason in favour is convenience (no adapter needed). The argument
|
||||
against is that if built-in files have this but (say) ``StringIO``
|
||||
does not, then code that uses "with" on a file object can't be
|
||||
reused with a ``StringIO`` object. So ``__exit__ = close`` becomes a part
|
||||
of the "file-like object" protocol, which user-defined classes may
|
||||
need to support.
|
||||
|
||||
The __enter__ hook may be unnecessary - for many use cases, an
|
||||
adapter class is needed and in that case, the work done by the
|
||||
__enter__ hook can just as easily be done in the __init__ hook.
|
||||
The ``__enter__`` hook may be unnecessary - for many use cases, an
|
||||
adapter class is needed and in that case, the work done by the
|
||||
``__enter__`` hook can just as easily be done in the ``__init__`` hook.
|
||||
|
||||
If a way of controlling object lifetimes explicitly was available,
|
||||
the function of the __exit__ hook could be taken over by the
|
||||
existing __del__ hook. An email exchange[1] with a proponent of
|
||||
this approach left one of the authors even more convinced that
|
||||
it isn't the right idea...
|
||||
If a way of controlling object lifetimes explicitly was available,
|
||||
the function of the ``__exit__`` hook could be taken over by the
|
||||
existing ``__del__`` hook. An email exchange [1]_ with a proponent of
|
||||
this approach left one of the authors even more convinced that
|
||||
it isn't the right idea...
|
||||
|
||||
It has been suggested[2] that the "__exit__" method be called
|
||||
"close", or that a "close" method should be considered if no
|
||||
__exit__ method is found, to increase the "out-of-the-box utility"
|
||||
of the "with ..." construct.
|
||||
It has been suggested [2]_ that the "__exit__" method be called
|
||||
"close", or that a "close" method should be considered if no
|
||||
``__exit__`` method is found, to increase the "out-of-the-box utility"
|
||||
of the "with ..." construct.
|
||||
|
||||
There are some similarities in concept between 'with ...' blocks
|
||||
and generators, which have led to proposals that for loops could
|
||||
implement the with block functionality[3]. While neat on some
|
||||
levels, we think that for loops should stick to being loops.
|
||||
There are some similarities in concept between 'with ...' blocks
|
||||
and generators, which have led to proposals that for loops could
|
||||
implement the with block functionality [3]_. While neat on some
|
||||
levels, we think that for loops should stick to being loops.
|
||||
|
||||
|
||||
Alternative Ideas
|
||||
=================
|
||||
|
||||
IEXEC: Holger Krekel -- generalised approach with XML-like syntax
|
||||
(no URL found...)
|
||||
IEXEC: Holger Krekel -- generalised approach with XML-like syntax
|
||||
(no URL found...)
|
||||
|
||||
Holger has much more far-reaching ideas about "execution monitors"
|
||||
that are informed about details of control flow in the monitored
|
||||
block. While interesting, these ideas could change the language
|
||||
in deep and subtle ways and as such belong to a different PEP.
|
||||
Holger has much more far-reaching ideas about "execution monitors"
|
||||
that are informed about details of control flow in the monitored
|
||||
block. While interesting, these ideas could change the language
|
||||
in deep and subtle ways and as such belong to a different PEP.
|
||||
|
||||
Any Smalltalk/Ruby anonymous block style extension obviously
|
||||
subsumes this one.
|
||||
Any Smalltalk/Ruby anonymous block style extension obviously
|
||||
subsumes this one.
|
||||
|
||||
PEP 319 is in the same area, but did not win support when aired on
|
||||
python-dev.
|
||||
PEP 319 is in the same area, but did not win support when aired on
|
||||
python-dev.
|
||||
|
||||
|
||||
Backwards Compatibility
|
||||
=======================
|
||||
|
||||
This PEP proposes a new keyword, so the __future__ game will need
|
||||
to be played.
|
||||
This PEP proposes a new keyword, so the ``__future__`` game will need
|
||||
to be played.
|
||||
|
||||
|
||||
Cost of Adoption
|
||||
================
|
||||
|
||||
Those who claim the language is getting larger and more
|
||||
complicated have something else to complain about. It's something
|
||||
else to teach.
|
||||
Those who claim the language is getting larger and more
|
||||
complicated have something else to complain about. It's something
|
||||
else to teach.
|
||||
|
||||
For the proposal to be useful, many file-like and lock-like
|
||||
classes in the standard library and other code will have to have
|
||||
For the proposal to be useful, many file-like and lock-like
|
||||
classes in the standard library and other code will have to have::
|
||||
|
||||
__exit__ = close
|
||||
__exit__ = close
|
||||
|
||||
or similar added.
|
||||
or similar added.
|
||||
|
||||
|
||||
Cost of Non-Adoption
|
||||
====================
|
||||
|
||||
Writing correct code continues to be more effort than writing
|
||||
incorrect code.
|
||||
Writing correct code continues to be more effort than writing
|
||||
incorrect code.
|
||||
|
||||
|
||||
References
|
||||
==========
|
||||
|
||||
There are various python-list and python-dev discussions that
|
||||
could be mentioned here.
|
||||
There are various python-list and python-dev discussions that
|
||||
could be mentioned here.
|
||||
|
||||
[1] Off-list conversation between Michael Hudson and Bill Soudan
|
||||
(made public with permission)
|
||||
http://starship.python.net/crew/mwh/pep310/
|
||||
.. [1] Off-list conversation between Michael Hudson and Bill Soudan
|
||||
(made public with permission)
|
||||
http://starship.python.net/crew/mwh/pep310/
|
||||
|
||||
[2] Samuele Pedroni on python-dev
|
||||
http://mail.python.org/pipermail/python-dev/2003-August/037795.html
|
||||
.. [2] Samuele Pedroni on python-dev
|
||||
http://mail.python.org/pipermail/python-dev/2003-August/037795.html
|
||||
|
||||
[3] Thread on python-dev with subject
|
||||
.. [3] Thread on python-dev with subject
|
||||
|
||||
[Python-Dev] pre-PEP: Resource-Release Support for Generators
|
||||
.. [Python-Dev] pre-PEP: Resource-Release Support for Generators
|
||||
|
||||
starting at
|
||||
starting at
|
||||
|
||||
http://mail.python.org/pipermail/python-dev/2003-August/037803.html
|
||||
http://mail.python.org/pipermail/python-dev/2003-August/037803.html
|
||||
|
||||
Copyright
|
||||
=========
|
||||
|
||||
This document has been placed in the public domain.
|
||||
This document has been placed in the public domain.
|
||||
|
||||
|
||||
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
sentence-end-double-space: t
|
||||
fill-column: 70
|
||||
End:
|
||||
|
||||
..
|
||||
Local Variables:
|
||||
mode: indented-text
|
||||
indent-tabs-mode: nil
|
||||
sentence-end-double-space: t
|
||||
fill-column: 70
|
||||
End:
|
||||
|
|
Loading…
Reference in New Issue