Convert 10 PEPs to reSt (#180)
This commit is contained in:
parent
fdc405df22
commit
87dc92a34e
195
pep-0212.txt
195
pep-0212.txt
|
@ -5,163 +5,180 @@ Last-Modified: $Date$
|
||||||
Author: nowonder@nowonder.de (Peter Schneider-Kamp)
|
Author: nowonder@nowonder.de (Peter Schneider-Kamp)
|
||||||
Status: Deferred
|
Status: Deferred
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 22-Aug-2000
|
Created: 22-Aug-2000
|
||||||
Python-Version: 2.1
|
Python-Version: 2.1
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
This PEP describes the often proposed feature of exposing the loop
|
This PEP describes the often proposed feature of exposing the loop
|
||||||
counter in for-loops. This PEP tracks the status and ownership of
|
counter in for-loops. This PEP tracks the status and ownership of
|
||||||
this feature. It contains a description of the feature and
|
this feature. It contains a description of the feature and
|
||||||
outlines changes necessary to support the feature. This PEP
|
outlines changes necessary to support the feature. This PEP
|
||||||
summarizes discussions held in mailing list forums, and provides
|
summarizes discussions held in mailing list forums, and provides
|
||||||
URLs for further information, where appropriate. The CVS revision
|
URLs for further information, where appropriate. The CVS revision
|
||||||
history of this file contains the definitive historical record.
|
history of this file contains the definitive historical record.
|
||||||
|
|
||||||
|
|
||||||
Motivation
|
Motivation
|
||||||
|
==========
|
||||||
|
|
||||||
Standard for-loops in Python iterate over the elements of a
|
Standard for-loops in Python iterate over the elements of a
|
||||||
sequence[1]. Often it is desirable to loop over the indices or
|
sequence [1]_. Often it is desirable to loop over the indices or
|
||||||
both the elements and the indices instead.
|
both the elements and the indices instead.
|
||||||
|
|
||||||
The common idioms used to accomplish this are unintuitive. This
|
The common idioms used to accomplish this are unintuitive. This
|
||||||
PEP proposes two different ways of exposing the indices.
|
PEP proposes two different ways of exposing the indices.
|
||||||
|
|
||||||
|
|
||||||
Loop counter iteration
|
Loop counter iteration
|
||||||
|
======================
|
||||||
|
|
||||||
The current idiom for looping over the indices makes use of the
|
The current idiom for looping over the indices makes use of the
|
||||||
built-in 'range' function:
|
built-in ``range`` function::
|
||||||
|
|
||||||
for i in range(len(sequence)):
|
for i in range(len(sequence)):
|
||||||
# work with index i
|
# work with index i
|
||||||
|
|
||||||
Looping over both elements and indices can be achieved either by the
|
Looping over both elements and indices can be achieved either by the
|
||||||
old idiom or by using the new 'zip' built-in function[2]:
|
old idiom or by using the new ``zip`` built-in function [2]_::
|
||||||
|
|
||||||
for i in range(len(sequence)):
|
for i in range(len(sequence)):
|
||||||
e = sequence[i]
|
e = sequence[i]
|
||||||
# work with index i and element e
|
# work with index i and element e
|
||||||
|
|
||||||
or
|
or::
|
||||||
|
|
||||||
for i, e in zip(range(len(sequence)), sequence):
|
for i, e in zip(range(len(sequence)), sequence):
|
||||||
# work with index i and element e
|
# work with index i and element e
|
||||||
|
|
||||||
|
|
||||||
The Proposed Solutions
|
The Proposed Solutions
|
||||||
|
======================
|
||||||
|
|
||||||
There are three solutions that have been discussed. One adds a
|
There are three solutions that have been discussed. One adds a
|
||||||
non-reserved keyword, the other adds two built-in functions.
|
non-reserved keyword, the other adds two built-in functions.
|
||||||
A third solution adds methods to sequence objects.
|
A third solution adds methods to sequence objects.
|
||||||
|
|
||||||
|
|
||||||
Non-reserved keyword 'indexing'
|
Non-reserved keyword ``indexing``
|
||||||
|
=================================
|
||||||
|
|
||||||
This solution would extend the syntax of the for-loop by adding
|
This solution would extend the syntax of the for-loop by adding
|
||||||
an optional '<variable> indexing' clause which can also be used
|
an optional ``<variable> indexing`` clause which can also be used
|
||||||
instead of the '<variable> in' clause..
|
instead of the ``<variable> in`` clause.
|
||||||
|
|
||||||
Looping over the indices of a sequence would thus become:
|
Looping over the indices of a sequence would thus become::
|
||||||
|
|
||||||
for i indexing sequence:
|
for i indexing sequence:
|
||||||
# work with index i
|
# work with index i
|
||||||
|
|
||||||
Looping over both indices and elements would similarly be:
|
Looping over both indices and elements would similarly be::
|
||||||
|
|
||||||
for i indexing e in sequence:
|
for i indexing e in sequence:
|
||||||
# work with index i and element e
|
# work with index i and element e
|
||||||
|
|
||||||
|
|
||||||
Built-in functions 'indices' and 'irange'
|
Built-in functions ``indices`` and ``irange``
|
||||||
|
=============================================
|
||||||
|
|
||||||
This solution adds two built-in functions 'indices' and 'irange'.
|
This solution adds two built-in functions ``indices`` and ``irange``.
|
||||||
The semantics of these can be described as follows:
|
The semantics of these can be described as follows::
|
||||||
|
|
||||||
def indices(sequence):
|
def indices(sequence):
|
||||||
return range(len(sequence))
|
return range(len(sequence))
|
||||||
|
|
||||||
def irange(sequence):
|
def irange(sequence):
|
||||||
return zip(range(len(sequence)), sequence)
|
return zip(range(len(sequence)), sequence)
|
||||||
|
|
||||||
These functions could be implemented either eagerly or lazily and
|
These functions could be implemented either eagerly or lazily and
|
||||||
should be easy to extend in order to accept more than one sequence
|
should be easy to extend in order to accept more than one sequence
|
||||||
argument.
|
argument.
|
||||||
|
|
||||||
The use of these functions would simplify the idioms for looping
|
The use of these functions would simplify the idioms for looping
|
||||||
over the indices and over both elements and indices:
|
over the indices and over both elements and indices::
|
||||||
|
|
||||||
for i in indices(sequence):
|
for i in indices(sequence):
|
||||||
# work with index i
|
# work with index i
|
||||||
|
|
||||||
for i, e in irange(sequence):
|
for i, e in irange(sequence):
|
||||||
# work with index i and element e
|
# work with index i and element e
|
||||||
|
|
||||||
|
|
||||||
Methods for sequence objects
|
Methods for sequence objects
|
||||||
|
============================
|
||||||
|
|
||||||
This solution proposes the addition of 'indices', 'items'
|
This solution proposes the addition of ``indices``, ``items``
|
||||||
and 'values' methods to sequences, which enable looping over
|
and ``values`` methods to sequences, which enable looping over
|
||||||
indices only, both indices and elements, and elements only
|
indices only, both indices and elements, and elements only
|
||||||
respectively.
|
respectively.
|
||||||
|
|
||||||
This would immensely simplify the idioms for looping over indices
|
This would immensely simplify the idioms for looping over indices
|
||||||
and for looping over both elements and indices:
|
and for looping over both elements and indices::
|
||||||
|
|
||||||
for i in sequence.indices():
|
for i in sequence.indices():
|
||||||
# work with index i
|
# work with index i
|
||||||
|
|
||||||
for i, e in sequence.items():
|
for i, e in sequence.items():
|
||||||
# work with index i and element e
|
# work with index i and element e
|
||||||
|
|
||||||
Additionally it would allow to do looping over the elements
|
Additionally it would allow to do looping over the elements
|
||||||
of sequences and dicitionaries in a consistent way:
|
of sequences and dictionaries in a consistent way::
|
||||||
|
|
||||||
for e in sequence_or_dict.values():
|
for e in sequence_or_dict.values():
|
||||||
# do something with element e
|
# do something with element e
|
||||||
|
|
||||||
|
|
||||||
Implementations
|
Implementations
|
||||||
|
===============
|
||||||
|
|
||||||
For all three solutions some more or less rough patches exist
|
For all three solutions some more or less rough patches exist
|
||||||
as patches at SourceForge:
|
as patches at SourceForge:
|
||||||
|
|
||||||
'for i indexing a in l': exposing the for-loop counter[3]
|
- ``for i indexing a in l``: exposing the for-loop counter [3]_
|
||||||
add indices() and irange() to built-ins[4]
|
- add ``indices()`` and ``irange()`` to built-ins [4]_
|
||||||
add items() method to listobject[5]
|
- add ``items()`` method to listobject [5]_
|
||||||
|
|
||||||
All of them have been pronounced on and rejected by the BDFL.
|
All of them have been pronounced on and rejected by the BDFL.
|
||||||
|
|
||||||
Note that the 'indexing' keyword is only a NAME in the
|
Note that the ``indexing`` keyword is only a ``NAME`` in the
|
||||||
grammar and so does not hinder the general use of 'indexing'.
|
grammar and so does not hinder the general use of ``indexing``.
|
||||||
|
|
||||||
|
|
||||||
Backward Compatibility Issues
|
Backward Compatibility Issues
|
||||||
|
=============================
|
||||||
|
|
||||||
As no keywords are added and the semantics of existing code
|
As no keywords are added and the semantics of existing code
|
||||||
remains unchanged, all three solutions can be implemented
|
remains unchanged, all three solutions can be implemented
|
||||||
without breaking existing code.
|
without breaking existing code.
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
[1] http://docs.python.org/reference/compound_stmts.html#for
|
.. [1] http://docs.python.org/reference/compound_stmts.html#for
|
||||||
[2] Lockstep Iteration, PEP 201
|
|
||||||
[3] http://sourceforge.net/patch/download.php?id=101138
|
.. [2] Lockstep Iteration, PEP 201
|
||||||
[4] http://sourceforge.net/patch/download.php?id=101129
|
|
||||||
[5] http://sourceforge.net/patch/download.php?id=101178
|
.. [3] http://sourceforge.net/patch/download.php?id=101138
|
||||||
|
|
||||||
|
.. [4] http://sourceforge.net/patch/download.php?id=101129
|
||||||
|
|
||||||
|
.. [5] http://sourceforge.net/patch/download.php?id=101178
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
End:
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
201
pep-0216.txt
201
pep-0216.txt
|
@ -5,139 +5,164 @@ Last-Modified: $Date$
|
||||||
Author: moshez@zadka.site.co.il (Moshe Zadka)
|
Author: moshez@zadka.site.co.il (Moshe Zadka)
|
||||||
Status: Rejected
|
Status: Rejected
|
||||||
Type: Informational
|
Type: Informational
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 31-Jul-2000
|
Created: 31-Jul-2000
|
||||||
Post-History:
|
Post-History:
|
||||||
Superseded-By: 287
|
Superseded-By: 287
|
||||||
|
|
||||||
Notice
|
|
||||||
|
|
||||||
This PEP is rejected by the author. It has been superseded by PEP
|
Notice
|
||||||
287.
|
======
|
||||||
|
|
||||||
|
This PEP is rejected by the author. It has been superseded by PEP
|
||||||
|
287.
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
Named Python objects, such as modules, classes and functions, have a
|
Named Python objects, such as modules, classes and functions, have a
|
||||||
string attribute called __doc__. If the first expression inside
|
string attribute called ``__doc__``. If the first expression inside
|
||||||
the definition is a literal string, that string is assigned
|
the definition is a literal string, that string is assigned
|
||||||
to the __doc__ attribute.
|
to the ``__doc__`` attribute.
|
||||||
|
|
||||||
|
The ``__doc__`` attribute is called a documentation string, or docstring.
|
||||||
|
It is often used to summarize the interface of the module, class or
|
||||||
|
function. However, since there is no common format for documentation
|
||||||
|
string, tools for extracting docstrings and transforming those into
|
||||||
|
documentation in a standard format (e.g., DocBook) have not sprang
|
||||||
|
up in abundance, and those that do exist are for the most part
|
||||||
|
unmaintained and unused.
|
||||||
|
|
||||||
The __doc__ attribute is called a documentation string, or docstring.
|
|
||||||
It is often used to summarize the interface of the module, class or
|
|
||||||
function. However, since there is no common format for documentation
|
|
||||||
string, tools for extracting docstrings and transforming those into
|
|
||||||
documentation in a standard format (e.g., DocBook) have not sprang
|
|
||||||
up in abundance, and those that do exist are for the most part
|
|
||||||
unmaintained and unused.
|
|
||||||
|
|
||||||
Perl Documentation
|
Perl Documentation
|
||||||
|
==================
|
||||||
|
|
||||||
|
In Perl, most modules are documented in a format called POD -- Plain
|
||||||
|
Old Documentation. This is an easy-to-type, very low level format
|
||||||
|
which integrates well with the Perl parser. Many tools exist to turn
|
||||||
|
POD documentation into other formats: info, HTML and man pages, among
|
||||||
|
others. However, in Perl, the information is not available at run-time.
|
||||||
|
|
||||||
In Perl, most modules are documented in a format called POD -- Plain
|
|
||||||
Old Documentation. This is an easy-to-type, very low level format
|
|
||||||
which integrates well with the Perl parser. Many tools exist to turn
|
|
||||||
POD documentation into other formats: info, HTML and man pages, among
|
|
||||||
others. However, in Perl, the information is not available at run-time.
|
|
||||||
|
|
||||||
Java Documentation
|
Java Documentation
|
||||||
|
==================
|
||||||
|
|
||||||
|
In Java, special comments before classes and functions function to
|
||||||
|
document the code. A program to extract these, and turn them into
|
||||||
|
HTML documentation is called javadoc, and is part of the standard
|
||||||
|
Java distribution. However, the only output format that is supported
|
||||||
|
is HTML, and JavaDoc has a very intimate relationship with HTML.
|
||||||
|
|
||||||
In Java, special comments before classes and functions function to
|
|
||||||
document the code. A program to extract these, and turn them into
|
|
||||||
HTML documentation is called javadoc, and is part of the standard
|
|
||||||
Java distribution. However, the only output format that is supported
|
|
||||||
is HTML, and JavaDoc has a very intimate relationship with HTML.
|
|
||||||
|
|
||||||
Python Docstring Goals
|
Python Docstring Goals
|
||||||
|
======================
|
||||||
|
|
||||||
|
Python documentation string are easy to spot during parsing, and are
|
||||||
|
also available to the runtime interpreter. This double purpose is
|
||||||
|
a bit problematic, sometimes: for example, some are reluctant to have
|
||||||
|
too long docstrings, because they do not want to take much space in
|
||||||
|
the runtime. In addition, because of the current lack of tools, people
|
||||||
|
read objects' docstrings by "print"ing them, so a tendency to make them
|
||||||
|
brief and free of markups has sprung up. This tendency hinders writing
|
||||||
|
better documentation-extraction tools, since it causes docstrings to
|
||||||
|
contain little information, which is hard to parse.
|
||||||
|
|
||||||
Python documentation string are easy to spot during parsing, and are
|
|
||||||
also available to the runtime interpreter. This double purpose is
|
|
||||||
a bit problematic, sometimes: for example, some are reluctant to have
|
|
||||||
too long docstrings, because they do not want to take much space in
|
|
||||||
the runtime. In addition, because of the current lack of tools, people
|
|
||||||
read objects' docstrings by "print"ing them, so a tendency to make them
|
|
||||||
brief and free of markups has sprung up. This tendency hinders writing
|
|
||||||
better documentation-extraction tools, since it causes docstrings to
|
|
||||||
contain little information, which is hard to parse.
|
|
||||||
|
|
||||||
High Level Solutions
|
High Level Solutions
|
||||||
|
====================
|
||||||
|
|
||||||
|
To counter the objection that the strings take up place in the running
|
||||||
|
program, it is suggested that documentation extraction tools will
|
||||||
|
concatenate a maximum prefix of string literals which appear in the
|
||||||
|
beginning of a definition. The first of these will also be available
|
||||||
|
in the interactive interpreter, so it should contain a few summary
|
||||||
|
lines.
|
||||||
|
|
||||||
To counter the objection that the strings take up place in the running
|
|
||||||
program, it is suggested that documentation extraction tools will
|
|
||||||
concatenate a maximum prefix of string literals which appear in the
|
|
||||||
beginning of a definition. The first of these will also be available
|
|
||||||
in the interactive interpreter, so it should contain a few summary
|
|
||||||
lines.
|
|
||||||
|
|
||||||
Docstring Format Goals
|
Docstring Format Goals
|
||||||
|
======================
|
||||||
|
|
||||||
These are the goals for the docstring format, as discussed ad neasum
|
These are the goals for the docstring format, as discussed ad nauseam
|
||||||
in the doc-sig.
|
in the doc-sig.
|
||||||
|
|
||||||
|
1. It must be easy to type with any standard text editor.
|
||||||
|
2. It must be readable to the casual observer.
|
||||||
|
3. It must not contain information which can be deduced from parsing
|
||||||
|
the module.
|
||||||
|
4. It must contain sufficient information so it can be converted
|
||||||
|
to any reasonable markup format.
|
||||||
|
5. It must be possible to write a module's entire documentation in
|
||||||
|
docstrings, without feeling hampered by the markup language.
|
||||||
|
|
||||||
1. It must be easy to type with any standard text editor.
|
|
||||||
2. It must be readable to the casual observer.
|
|
||||||
3. It must not contain information which can be deduced from parsing
|
|
||||||
the module.
|
|
||||||
4. It must contain sufficient information so it can be converted
|
|
||||||
to any reasonable markup format.
|
|
||||||
5. It must be possible to write a module's entire documentation in
|
|
||||||
docstrings, without feeling hampered by the markup language.
|
|
||||||
|
|
||||||
Docstring Contents
|
Docstring Contents
|
||||||
|
==================
|
||||||
|
|
||||||
For requirement 5. above, it is needed to specify what must be
|
For requirement 5. above, it is needed to specify what must be
|
||||||
in docstrings.
|
in docstrings.
|
||||||
|
|
||||||
At least the following must be available:
|
At least the following must be available:
|
||||||
|
|
||||||
a. A tag that means "this is a Python ``something'', guess what"
|
a. A tag that means "this is a Python `something`, guess what"
|
||||||
|
|
||||||
Example: In the sentence "The POP3 class", we need to markup "POP3"
|
Example: In the sentence "The POP3 class", we need to markup "POP3"
|
||||||
so. The parser will be able to guess it is a class from the contents
|
so. The parser will be able to guess it is a class from the contents
|
||||||
of the poplib module, but we need to make it guess.
|
of the ``poplib`` module, but we need to make it guess.
|
||||||
|
|
||||||
b. Tags that mean "this is a Python class/module/class var/instance var..."
|
b. Tags that mean "this is a Python class/module/class var/instance var..."
|
||||||
|
|
||||||
Example: The usual Python idiom for singleton class A is to have _A
|
Example: The usual Python idiom for singleton class ``A`` is to have ``_A``
|
||||||
as the class, and A a function which returns _A objects. It's usual
|
as the class, and ``A`` a function which returns ``_A`` objects. It's usual
|
||||||
to document the class, nonetheless, as being A. This requires the
|
to document the class, nonetheless, as being ``A``. This requires the
|
||||||
strength to say "The class A" and have A hyperlinked and marked-up
|
strength to say "The class ``A``" and have ``A`` hyperlinked and marked-up
|
||||||
as a class.
|
as a class.
|
||||||
|
|
||||||
|
c. An easy way to include Python source code/Python interactive sessions
|
||||||
|
|
||||||
|
d. Emphasis/bold
|
||||||
|
|
||||||
|
e. List/tables
|
||||||
|
|
||||||
c. An easy way to include Python source code/Python interactive sessions
|
|
||||||
d. Emphasis/bold
|
|
||||||
e. List/tables
|
|
||||||
|
|
||||||
Docstring Basic Structure
|
Docstring Basic Structure
|
||||||
|
=========================
|
||||||
|
|
||||||
|
The documentation strings will be in StructuredTextNG
|
||||||
|
(http://www.zope.org/Members/jim/StructuredTextWiki/StructuredTextNG)
|
||||||
|
Since StructuredText is not yet strong enough to handle (a) and (b)
|
||||||
|
above, we will need to extend it. I suggest using
|
||||||
|
``[<optional description>:python identifier]``.
|
||||||
|
E.g.: ``[class:POP3]``, ``[:POP3.list]``, etc. If the description is missing,
|
||||||
|
a guess will be made from the text.
|
||||||
|
|
||||||
The documentation strings will be in StructuredTextNG
|
|
||||||
(http://www.zope.org/Members/jim/StructuredTextWiki/StructuredTextNG)
|
|
||||||
Since StructuredText is not yet strong enough to handle (a) and (b)
|
|
||||||
above, we will need to extend it. I suggest using
|
|
||||||
'[<optional description>:python identifier]'.
|
|
||||||
E.g.: [class:POP3], [:POP3.list], etc. If the description is missing,
|
|
||||||
a guess will be made from the text.
|
|
||||||
|
|
||||||
Unresolved Issues
|
Unresolved Issues
|
||||||
|
=================
|
||||||
Is there a way to escape characters in ST? If so, how?
|
|
||||||
(example: * at the beginning of a line without being bullet symbol)
|
|
||||||
|
|
||||||
Is my suggestion above for Python symbols compatible with ST-NG?
|
Is there a way to escape characters in ST? If so, how?
|
||||||
How hard would it be to extend ST-NG to support it?
|
(example: * at the beginning of a line without being bullet symbol)
|
||||||
|
|
||||||
How do we describe input and output types of functions?
|
Is my suggestion above for Python symbols compatible with ST-NG?
|
||||||
|
How hard would it be to extend ST-NG to support it?
|
||||||
|
|
||||||
What additional constraint do we enforce on each docstring?
|
How do we describe input and output types of functions?
|
||||||
(module/class/function)?
|
|
||||||
|
What additional constraint do we enforce on each docstring?
|
||||||
|
(module/class/function)?
|
||||||
|
|
||||||
|
What are the guesser rules?
|
||||||
|
|
||||||
What are the guesser rules?
|
|
||||||
|
|
||||||
Rejected Suggestions
|
Rejected Suggestions
|
||||||
|
====================
|
||||||
|
|
||||||
XML -- it's very hard to type, and too cluttered to read it
|
XML -- it's very hard to type, and too cluttered to read it comfortably.
|
||||||
comfortably.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
End:
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
282
pep-0219.txt
282
pep-0219.txt
|
@ -5,187 +5,195 @@ Last-Modified: $Date$
|
||||||
Author: gmcm@hypernet.com (Gordon McMillan)
|
Author: gmcm@hypernet.com (Gordon McMillan)
|
||||||
Status: Deferred
|
Status: Deferred
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 14-Aug-2000
|
Created: 14-Aug-2000
|
||||||
Python-Version: 2.1
|
Python-Version: 2.1
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Introduction
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
This PEP discusses changes required to core Python in order to
|
This PEP discusses changes required to core Python in order to
|
||||||
efficiently support generators, microthreads and coroutines. It is
|
efficiently support generators, microthreads and coroutines. It is
|
||||||
related to PEP 220, which describes how Python should be extended
|
related to PEP 220, which describes how Python should be extended
|
||||||
to support these facilities. The focus of this PEP is strictly on
|
to support these facilities. The focus of this PEP is strictly on
|
||||||
the changes required to allow these extensions to work.
|
the changes required to allow these extensions to work.
|
||||||
|
|
||||||
While these PEPs are based on Christian Tismer's Stackless[1]
|
While these PEPs are based on Christian Tismer's Stackless [1]_
|
||||||
implementation, they do not regard Stackless as a reference
|
implementation, they do not regard Stackless as a reference
|
||||||
implementation. Stackless (with an extension module) implements
|
implementation. Stackless (with an extension module) implements
|
||||||
continuations, and from continuations one can implement
|
continuations, and from continuations one can implement
|
||||||
coroutines, microthreads (as has been done by Will Ware[2]) and
|
coroutines, microthreads (as has been done by Will Ware [2]_) and
|
||||||
generators. But in more that a year, no one has found any other
|
generators. But in more that a year, no one has found any other
|
||||||
productive use of continuations, so there seems to be no demand
|
productive use of continuations, so there seems to be no demand
|
||||||
for their support.
|
for their support.
|
||||||
|
|
||||||
However, Stackless support for continuations is a relatively minor
|
However, Stackless support for continuations is a relatively minor
|
||||||
piece of the implementation, so one might regard it as "a"
|
piece of the implementation, so one might regard it as "a"
|
||||||
reference implementation (rather than "the" reference
|
reference implementation (rather than "the" reference
|
||||||
implementation).
|
implementation).
|
||||||
|
|
||||||
|
|
||||||
Background
|
Background
|
||||||
|
==========
|
||||||
|
|
||||||
Generators and coroutines have been implemented in a number of
|
Generators and coroutines have been implemented in a number of
|
||||||
languages in a number of ways. Indeed, Tim Peters has done pure
|
languages in a number of ways. Indeed, Tim Peters has done pure
|
||||||
Python implementations of generators[3] and coroutines[4] using
|
Python implementations of generators [3]_ and coroutines [4]_ using
|
||||||
threads (and a thread-based coroutine implementation exists for
|
threads (and a thread-based coroutine implementation exists for
|
||||||
Java). However, the horrendous overhead of a thread-based
|
Java). However, the horrendous overhead of a thread-based
|
||||||
implementation severely limits the usefulness of this approach.
|
implementation severely limits the usefulness of this approach.
|
||||||
|
|
||||||
Microthreads (a.k.a "green" or "user" threads) and coroutines
|
Microthreads (a.k.a "green" or "user" threads) and coroutines
|
||||||
involve transfers of control that are difficult to accommodate in
|
involve transfers of control that are difficult to accommodate in
|
||||||
a language implementation based on a single stack. (Generators can
|
a language implementation based on a single stack. (Generators can
|
||||||
be done on a single stack, but they can also be regarded as a very
|
be done on a single stack, but they can also be regarded as a very
|
||||||
simple case of coroutines.)
|
simple case of coroutines.)
|
||||||
|
|
||||||
Real threads allocate a full-sized stack for each thread of
|
Real threads allocate a full-sized stack for each thread of
|
||||||
control, and this is the major source of overhead. However,
|
control, and this is the major source of overhead. However,
|
||||||
coroutines and microthreads can be implemented in Python in a way
|
coroutines and microthreads can be implemented in Python in a way
|
||||||
that involves almost no overhead. This PEP, therefor, offers a
|
that involves almost no overhead. This PEP, therefor, offers a
|
||||||
way for making Python able to realistically manage thousands of
|
way for making Python able to realistically manage thousands of
|
||||||
separate "threads" of activity (vs. today's limit of perhaps dozens
|
separate "threads" of activity (vs. today's limit of perhaps dozens
|
||||||
of separate threads of activity).
|
of separate threads of activity).
|
||||||
|
|
||||||
Another justification for this PEP (explored in PEP 220) is that
|
Another justification for this PEP (explored in PEP 220) is that
|
||||||
coroutines and generators often allow a more direct expression of
|
coroutines and generators often allow a more direct expression of
|
||||||
an algorithm than is possible in today's Python.
|
an algorithm than is possible in today's Python.
|
||||||
|
|
||||||
|
|
||||||
Discussion
|
Discussion
|
||||||
|
==========
|
||||||
|
|
||||||
The first thing to note is that Python, while it mingles
|
The first thing to note is that Python, while it mingles
|
||||||
interpreter data (normal C stack usage) with Python data (the
|
interpreter data (normal C stack usage) with Python data (the
|
||||||
state of the interpreted program) on the stack, the two are
|
state of the interpreted program) on the stack, the two are
|
||||||
logically separate. They just happen to use the same stack.
|
logically separate. They just happen to use the same stack.
|
||||||
|
|
||||||
A real thread gets something approaching a process-sized stack
|
A real thread gets something approaching a process-sized stack
|
||||||
because the implementation has no way of knowing how much stack
|
because the implementation has no way of knowing how much stack
|
||||||
space the thread will require. The stack space required for an
|
space the thread will require. The stack space required for an
|
||||||
individual frame is likely to be reasonable, but stack switching
|
individual frame is likely to be reasonable, but stack switching
|
||||||
is an arcane and non-portable process, not supported by C.
|
is an arcane and non-portable process, not supported by C.
|
||||||
|
|
||||||
Once Python stops putting Python data on the C stack, however,
|
Once Python stops putting Python data on the C stack, however,
|
||||||
stack switching becomes easy.
|
stack switching becomes easy.
|
||||||
|
|
||||||
The fundamental approach of the PEP is based on these two
|
The fundamental approach of the PEP is based on these two
|
||||||
ideas. First, separate C's stack usage from Python's stack
|
ideas. First, separate C's stack usage from Python's stack
|
||||||
usage. Secondly, associate with each frame enough stack space to
|
usage. Secondly, associate with each frame enough stack space to
|
||||||
handle that frame's execution.
|
handle that frame's execution.
|
||||||
|
|
||||||
In the normal usage, Stackless Python has a normal stack
|
In the normal usage, Stackless Python has a normal stack
|
||||||
structure, except that it is broken into chunks. But in the
|
structure, except that it is broken into chunks. But in the
|
||||||
presence of a coroutine / microthread extension, this same
|
presence of a coroutine / microthread extension, this same
|
||||||
mechanism supports a stack with a tree structure. That is, an
|
mechanism supports a stack with a tree structure. That is, an
|
||||||
extension can support transfers of control between frames outside
|
extension can support transfers of control between frames outside
|
||||||
the normal "call / return" path.
|
the normal "call / return" path.
|
||||||
|
|
||||||
|
|
||||||
Problems
|
Problems
|
||||||
|
========
|
||||||
|
|
||||||
The major difficulty with this approach is C calling Python. The
|
The major difficulty with this approach is C calling Python. The
|
||||||
problem is that the C stack now holds a nested execution of the
|
problem is that the C stack now holds a nested execution of the
|
||||||
byte-code interpreter. In that situation, a coroutine /
|
byte-code interpreter. In that situation, a coroutine /
|
||||||
microthread extension cannot be permitted to transfer control to a
|
microthread extension cannot be permitted to transfer control to a
|
||||||
frame in a different invocation of the byte-code interpreter. If a
|
frame in a different invocation of the byte-code interpreter. If a
|
||||||
frame were to complete and exit back to C from the wrong
|
frame were to complete and exit back to C from the wrong
|
||||||
interpreter, the C stack could be trashed.
|
interpreter, the C stack could be trashed.
|
||||||
|
|
||||||
The ideal solution is to create a mechanism where nested
|
The ideal solution is to create a mechanism where nested
|
||||||
executions of the byte code interpreter are never needed. The easy
|
executions of the byte code interpreter are never needed. The easy
|
||||||
solution is for the coroutine / microthread extension(s) to
|
solution is for the coroutine / microthread extension(s) to
|
||||||
recognize the situation and refuse to allow transfers outside the
|
recognize the situation and refuse to allow transfers outside the
|
||||||
current invocation.
|
current invocation.
|
||||||
|
|
||||||
We can categorize code that involves C calling Python into two
|
We can categorize code that involves C calling Python into two
|
||||||
camps: Python's implementation, and C extensions. And hopefully we
|
camps: Python's implementation, and C extensions. And hopefully we
|
||||||
can offer a compromise: Python's internal usage (and C extension
|
can offer a compromise: Python's internal usage (and C extension
|
||||||
writers who want to go to the effort) will no longer use a nested
|
writers who want to go to the effort) will no longer use a nested
|
||||||
invocation of the interpreter. Extensions which do not go to the
|
invocation of the interpreter. Extensions which do not go to the
|
||||||
effort will still be safe, but will not play well with coroutines
|
effort will still be safe, but will not play well with coroutines
|
||||||
/ microthreads.
|
/ microthreads.
|
||||||
|
|
||||||
Generally, when a recursive call is transformed into a loop, a bit
|
Generally, when a recursive call is transformed into a loop, a bit
|
||||||
of extra bookkeeping is required. The loop will need to keep its
|
of extra bookkeeping is required. The loop will need to keep its
|
||||||
own "stack" of arguments and results since the real stack can now
|
own "stack" of arguments and results since the real stack can now
|
||||||
only hold the most recent. The code will be more verbose, because
|
only hold the most recent. The code will be more verbose, because
|
||||||
it's not quite as obvious when we're done. While Stackless is not
|
it's not quite as obvious when we're done. While Stackless is not
|
||||||
implemented this way, it has to deal with the same issues.
|
implemented this way, it has to deal with the same issues.
|
||||||
|
|
||||||
In normal Python, PyEval_EvalCode is used to build a frame and
|
In normal Python, ``PyEval_EvalCode`` is used to build a frame and
|
||||||
execute it. Stackless Python introduces the concept of a
|
execute it. Stackless Python introduces the concept of a
|
||||||
FrameDispatcher. Like PyEval_EvalCode, it executes one frame. But
|
``FrameDispatcher``. Like ``PyEval_EvalCode``, it executes one frame. But
|
||||||
the interpreter may signal the FrameDispatcher that a new frame
|
the interpreter may signal the ``FrameDispatcher`` that a new frame
|
||||||
has been swapped in, and the new frame should be executed. When a
|
has been swapped in, and the new frame should be executed. When a
|
||||||
frame completes, the FrameDispatcher follows the back pointer to
|
frame completes, the ``FrameDispatcher`` follows the back pointer to
|
||||||
resume the "calling" frame.
|
resume the "calling" frame.
|
||||||
|
|
||||||
So Stackless transforms recursions into a loop, but it is not the
|
So Stackless transforms recursions into a loop, but it is not the
|
||||||
FrameDispatcher that manages the frames. This is done by the
|
``FrameDispatcher`` that manages the frames. This is done by the
|
||||||
interpreter (or an extension that knows what it's doing).
|
interpreter (or an extension that knows what it's doing).
|
||||||
|
|
||||||
The general idea is that where C code needs to execute Python
|
The general idea is that where C code needs to execute Python
|
||||||
code, it creates a frame for the Python code, setting its back
|
code, it creates a frame for the Python code, setting its back
|
||||||
pointer to the current frame. Then it swaps in the frame, signals
|
pointer to the current frame. Then it swaps in the frame, signals
|
||||||
the FrameDispatcher and gets out of the way. The C stack is now
|
the ``FrameDispatcher`` and gets out of the way. The C stack is now
|
||||||
clean - the Python code can transfer control to any other frame
|
clean - the Python code can transfer control to any other frame
|
||||||
(if an extension gives it the means to do so).
|
(if an extension gives it the means to do so).
|
||||||
|
|
||||||
In the vanilla case, this magic can be hidden from the programmer
|
In the vanilla case, this magic can be hidden from the programmer
|
||||||
(even, in most cases, from the Python-internals programmer). Many
|
(even, in most cases, from the Python-internals programmer). Many
|
||||||
situations present another level of difficulty, however.
|
situations present another level of difficulty, however.
|
||||||
|
|
||||||
The map builtin function involves two obstacles to this
|
The map builtin function involves two obstacles to this
|
||||||
approach. It cannot simply construct a frame and get out of the
|
approach. It cannot simply construct a frame and get out of the
|
||||||
way, not just because there's a loop involved, but each pass
|
way, not just because there's a loop involved, but each pass
|
||||||
through the loop requires some "post" processing. In order to play
|
through the loop requires some "post" processing. In order to play
|
||||||
well with others, Stackless constructs a frame object for map
|
well with others, Stackless constructs a frame object for map
|
||||||
itself.
|
itself.
|
||||||
|
|
||||||
|
Most recursions of the interpreter are not this complex, but
|
||||||
|
fairly frequently, some "post" operations are required. Stackless
|
||||||
|
does not fix these situations because of amount of code changes
|
||||||
|
required. Instead, Stackless prohibits transfers out of a nested
|
||||||
|
interpreter. While not ideal (and sometimes puzzling), this
|
||||||
|
limitation is hardly crippling.
|
||||||
|
|
||||||
Most recursions of the interpreter are not this complex, but
|
|
||||||
fairly frequently, some "post" operations are required. Stackless
|
|
||||||
does not fix these situations because of amount of code changes
|
|
||||||
required. Instead, Stackless prohibits transfers out of a nested
|
|
||||||
interpreter. While not ideal (and sometimes puzzling), this
|
|
||||||
limitation is hardly crippling.
|
|
||||||
|
|
||||||
|
|
||||||
Advantages
|
Advantages
|
||||||
|
==========
|
||||||
|
|
||||||
For normal Python, the advantage to this approach is that C stack
|
For normal Python, the advantage to this approach is that C stack
|
||||||
usage becomes much smaller and more predictable. Unbounded
|
usage becomes much smaller and more predictable. Unbounded
|
||||||
recursion in Python code becomes a memory error, instead of a
|
recursion in Python code becomes a memory error, instead of a
|
||||||
stack error (and thus, in non-Cupertino operating systems,
|
stack error (and thus, in non-Cupertino operating systems,
|
||||||
something that can be recovered from). The price, of course, is
|
something that can be recovered from). The price, of course, is
|
||||||
the added complexity that comes from transforming recursions of
|
the added complexity that comes from transforming recursions of
|
||||||
the byte-code interpreter loop into a higher order loop (and the
|
the byte-code interpreter loop into a higher order loop (and the
|
||||||
attendant bookkeeping involved).
|
attendant bookkeeping involved).
|
||||||
|
|
||||||
The big advantage comes from realizing that the Python stack is
|
The big advantage comes from realizing that the Python stack is
|
||||||
really a tree, and the frame dispatcher can transfer control
|
really a tree, and the frame dispatcher can transfer control
|
||||||
freely between leaf nodes of the tree, thus allowing things like
|
freely between leaf nodes of the tree, thus allowing things like
|
||||||
microthreads and coroutines.
|
microthreads and coroutines.
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
[1] http://www.stackless.com
|
.. [1] http://www.stackless.com
|
||||||
[2] http://world.std.com/~wware/uthread.html
|
.. [2] http://web.archive.org/web/20000815070602/http://world.std.com/~wware/uthread.html
|
||||||
[3] Demo/threads/Generator.py in the source distribution
|
.. [3] Demo/threads/Generator.py in the source distribution
|
||||||
[4] http://www.stackless.com/coroutines.tim.peters.html
|
.. [4] http://www.stackless.com/coroutines.tim.peters.html
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
End:
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
174
pep-0228.txt
174
pep-0228.txt
|
@ -5,140 +5,152 @@ Last-Modified: $Date$
|
||||||
Author: moshez@zadka.site.co.il (Moshe Zadka), guido@python.org (Guido van Rossum)
|
Author: moshez@zadka.site.co.il (Moshe Zadka), guido@python.org (Guido van Rossum)
|
||||||
Status: Withdrawn
|
Status: Withdrawn
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 4-Nov-2000
|
Created: 4-Nov-2000
|
||||||
Python-Version: ??
|
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Withdrawal
|
Withdrawal
|
||||||
|
==========
|
||||||
|
|
||||||
This PEP has been withdrawn in favor of PEP 3141.
|
This PEP has been withdrawn in favor of PEP 3141.
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
Today, Python's numerical model is similar to the C numeric model:
|
Today, Python's numerical model is similar to the C numeric model:
|
||||||
there are several unrelated numerical types, and when operations
|
there are several unrelated numerical types, and when operations
|
||||||
between numerical types are requested, coercions happen. While
|
between numerical types are requested, coercions happen. While
|
||||||
the C rationale for the numerical model is that it is very similar
|
the C rationale for the numerical model is that it is very similar
|
||||||
to what happens at the hardware level, that rationale does not
|
to what happens at the hardware level, that rationale does not
|
||||||
apply to Python. So, while it is acceptable to C programmers that
|
apply to Python. So, while it is acceptable to C programmers that
|
||||||
2/3 == 0, it is surprising to many Python programmers.
|
2/3 == 0, it is surprising to many Python programmers.
|
||||||
|
|
||||||
NOTE: in the light of recent discussions in the newsgroup, the
|
NOTE: in the light of recent discussions in the newsgroup, the
|
||||||
motivation in this PEP (and details) need to be extended.
|
motivation in this PEP (and details) need to be extended.
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
=========
|
||||||
|
|
||||||
In usability studies, one of the least usable aspect of Python was
|
In usability studies, one of the least usable aspect of Python was
|
||||||
the fact that integer division returns the floor of the division.
|
the fact that integer division returns the floor of the division.
|
||||||
This makes it hard to program correctly, requiring casts to
|
This makes it hard to program correctly, requiring casts to
|
||||||
float() in various parts through the code. Python's numerical
|
``float()`` in various parts through the code. Python's numerical
|
||||||
model stems from C, while a model that might be easier to work with
|
model stems from C, while a model that might be easier to work with
|
||||||
can be based on the mathematical understanding of numbers.
|
can be based on the mathematical understanding of numbers.
|
||||||
|
|
||||||
|
|
||||||
Other Numerical Models
|
Other Numerical Models
|
||||||
|
======================
|
||||||
|
|
||||||
Perl's numerical model is that there is one type of numbers --
|
Perl's numerical model is that there is one type of numbers --
|
||||||
floating point numbers. While it is consistent and superficially
|
floating point numbers. While it is consistent and superficially
|
||||||
non-surprising, it tends to have subtle gotchas. One of these is
|
non-surprising, it tends to have subtle gotchas. One of these is
|
||||||
that printing numbers is very tricky, and requires correct
|
that printing numbers is very tricky, and requires correct
|
||||||
rounding. In Perl, there is also a mode where all numbers are
|
rounding. In Perl, there is also a mode where all numbers are
|
||||||
integers. This mode also has its share of problems, which arise
|
integers. This mode also has its share of problems, which arise
|
||||||
from the fact that there is not even an approximate way of
|
from the fact that there is not even an approximate way of
|
||||||
dividing numbers and getting meaningful answers.
|
dividing numbers and getting meaningful answers.
|
||||||
|
|
||||||
|
|
||||||
Suggested Interface For Python's Numerical Model
|
Suggested Interface For Python's Numerical Model
|
||||||
|
================================================
|
||||||
|
|
||||||
While coercion rules will remain for add-on types and classes, the
|
While coercion rules will remain for add-on types and classes, the
|
||||||
built in type system will have exactly one Python type -- a
|
built in type system will have exactly one Python type -- a
|
||||||
number. There are several things which can be considered "number
|
number. There are several things which can be considered "number
|
||||||
methods":
|
methods":
|
||||||
|
|
||||||
1. isnatural()
|
1. ``isnatural()``
|
||||||
2. isintegral()
|
2. ``isintegral()``
|
||||||
3. isrational()
|
3. ``isrational()``
|
||||||
4. isreal()
|
4. ``isreal()``
|
||||||
5. iscomplex()
|
5. ``iscomplex()``
|
||||||
|
6. ``isexact()``
|
||||||
|
|
||||||
a. isexact()
|
Obviously, a number which answers true to a question from 1 to 5, will
|
||||||
|
also answer true to any following question. If ``isexact()`` is not true,
|
||||||
|
then any answer might be wrong.
|
||||||
|
(But not horribly wrong: it's close to the truth.)
|
||||||
|
|
||||||
Obviously, a number which answers true to a question from 1 to 5, will
|
Now, there is two thing the models promises for the field operations
|
||||||
also answer true to any following question. If "isexact()" is not true,
|
(+, -, /, \*):
|
||||||
then any answer might be wrong.
|
|
||||||
(But not horribly wrong: it's close to the truth.)
|
|
||||||
|
|
||||||
Now, there is two thing the models promises for the field operations
|
- If both operands satisfy ``isexact()``, the result satisfies
|
||||||
(+, -, /, *):
|
``isexact()``.
|
||||||
|
|
||||||
- If both operands satisfy isexact(), the result satisfies
|
- All field rules are true, except that for not-``isexact()`` numbers,
|
||||||
isexact().
|
they might be only approximately true.
|
||||||
|
|
||||||
- All field rules are true, except that for not-isexact() numbers,
|
One consequence of these two rules is that all exact calcutions
|
||||||
they might be only approximately true.
|
are done as (complex) rationals: since the field laws must hold,
|
||||||
|
then::
|
||||||
|
|
||||||
One consequence of these two rules is that all exact calcutions
|
(a/b)*b == a
|
||||||
are done as (complex) rationals: since the field laws must hold,
|
|
||||||
then
|
|
||||||
|
|
||||||
(a/b)*b == a
|
must hold.
|
||||||
|
|
||||||
must hold.
|
There is built-in function, ``inexact()`` which takes a number
|
||||||
|
and returns an inexact number which is a good approximation.
|
||||||
|
Inexact numbers must be as least as accurate as if they were
|
||||||
|
using IEEE-754.
|
||||||
|
|
||||||
There is built-in function, inexact() which takes a number
|
Several of the classical Python functions will return exact numbers
|
||||||
and returns an inexact number which is a good approximation.
|
even when given inexact numbers: e.g, ``int()``.
|
||||||
Inexact numbers must be as least as accurate as if they were
|
|
||||||
using IEEE-754.
|
|
||||||
|
|
||||||
Several of the classical Python functions will return exact numbers
|
|
||||||
even when given inexact numbers: e.g, int().
|
|
||||||
|
|
||||||
Coercion
|
Coercion
|
||||||
|
========
|
||||||
|
|
||||||
|
The number type does not define ``nb_coerce``
|
||||||
|
Any numeric operation slot, when receiving something other then ``PyNumber``,
|
||||||
|
refuses to implement it.
|
||||||
|
|
||||||
The number type does not define nb_coerce
|
|
||||||
Any numeric operation slot, when receiving something other then PyNumber,
|
|
||||||
refuses to implement it.
|
|
||||||
|
|
||||||
Inexact Operations
|
Inexact Operations
|
||||||
|
==================
|
||||||
|
|
||||||
The functions in the "math" module will be allowed to return
|
The functions in the ``math`` module will be allowed to return
|
||||||
inexact results for exact values. However, they will never return
|
inexact results for exact values. However, they will never return
|
||||||
a non-real number. The functions in the "cmath" module are also
|
a non-real number. The functions in the ``cmath`` module are also
|
||||||
allowed to return an inexact result for an exact argument, and are
|
allowed to return an inexact result for an exact argument, and are
|
||||||
furthermore allowed to return a complex result for a real
|
furthermore allowed to return a complex result for a real
|
||||||
argument.
|
argument.
|
||||||
|
|
||||||
|
|
||||||
Numerical Python Issues
|
Numerical Python Issues
|
||||||
|
=======================
|
||||||
|
|
||||||
People who use Numerical Python do so for high-performance vector
|
People who use Numerical Python do so for high-performance vector
|
||||||
operations. Therefore, NumPy should keep its hardware based
|
operations. Therefore, NumPy should keep its hardware based
|
||||||
numeric model.
|
numeric model.
|
||||||
|
|
||||||
|
|
||||||
Unresolved Issues
|
Unresolved Issues
|
||||||
|
=================
|
||||||
|
|
||||||
Which number literals will be exact, and which inexact?
|
Which number literals will be exact, and which inexact?
|
||||||
|
|
||||||
How do we deal with IEEE 754 operations? (probably, isnan/isinf should
|
How do we deal with IEEE 754 operations? (probably, isnan/isinf should
|
||||||
be methods)
|
be methods)
|
||||||
|
|
||||||
On 64-bit machines, comparisons between ints and floats may be
|
On 64-bit machines, comparisons between ints and floats may be
|
||||||
broken when the comparison involves conversion to float. Ditto
|
broken when the comparison involves conversion to float. Ditto
|
||||||
for comparisons between longs and floats. This can be dealt with
|
for comparisons between longs and floats. This can be dealt with
|
||||||
by avoiding the conversion to float. (Due to Andrew Koenig.)
|
by avoiding the conversion to float. (Due to Andrew Koenig.)
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
End:
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
202
pep-0235.txt
202
pep-0235.txt
|
@ -5,27 +5,30 @@ Last-Modified: $Date$
|
||||||
Author: Tim Peters <tim.peters@gmail.com>
|
Author: Tim Peters <tim.peters@gmail.com>
|
||||||
Status: Final
|
Status: Final
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created:
|
Created:
|
||||||
Python-Version: 2.1
|
Python-Version: 2.1
|
||||||
Post-History: 16 February 2001
|
Post-History: 16 February 2001
|
||||||
|
|
||||||
|
|
||||||
Note
|
Note
|
||||||
|
====
|
||||||
|
|
||||||
This is essentially a retroactive PEP: the issue came up too late
|
This is essentially a retroactive PEP: the issue came up too late
|
||||||
in the 2.1 release process to solicit wide opinion before deciding
|
in the 2.1 release process to solicit wide opinion before deciding
|
||||||
what to do, and can't be put off until 2.2 without also delaying
|
what to do, and can't be put off until 2.2 without also delaying
|
||||||
the Cygwin and MacOS X ports.
|
the Cygwin and MacOS X ports.
|
||||||
|
|
||||||
|
|
||||||
Motivation
|
Motivation
|
||||||
|
==========
|
||||||
|
|
||||||
File systems vary across platforms in whether or not they preserve
|
File systems vary across platforms in whether or not they preserve
|
||||||
the case of filenames, and in whether or not the platform C
|
the case of filenames, and in whether or not the platform C
|
||||||
library file-opening functions do or don't insist on
|
library file-opening functions do or don't insist on
|
||||||
case-sensitive matches:
|
case-sensitive matches::
|
||||||
|
|
||||||
case-preserving case-destroying
|
case-preserving case-destroying
|
||||||
+-------------------+------------------+
|
+-------------------+------------------+
|
||||||
case-sensitive | most Unix flavors | brrrrrrrrrr |
|
case-sensitive | most Unix flavors | brrrrrrrrrr |
|
||||||
+-------------------+------------------+
|
+-------------------+------------------+
|
||||||
|
@ -35,119 +38,122 @@ Motivation
|
||||||
| | OpenVMS |
|
| | OpenVMS |
|
||||||
+-------------------+------------------+
|
+-------------------+------------------+
|
||||||
|
|
||||||
In the upper left box, if you create "fiLe" it's stored as "fiLe",
|
In the upper left box, if you create "fiLe" it's stored as "fiLe",
|
||||||
and only open("fiLe") will open it (open("file") will not, nor
|
and only ``open("fiLe")`` will open it ``(open("file")`` will not, nor
|
||||||
will the 14 other variations on that theme).
|
will the 14 other variations on that theme).
|
||||||
|
|
||||||
In the lower right box, if you create "fiLe", there's no telling
|
In the lower right box, if you create "fiLe", there's no telling
|
||||||
what it's stored as -- but most likely as "FILE" -- and any of the
|
what it's stored as -- but most likely as "FILE" -- and any of the
|
||||||
16 obvious variations on open("FilE") will open it.
|
16 obvious variations on ``open("FilE")`` will open it.
|
||||||
|
|
||||||
The lower left box is a mix: creating "fiLe" stores "fiLe" in the
|
The lower left box is a mix: creating "fiLe" stores "fiLe" in the
|
||||||
platform directory, but you don't have to match case when opening
|
platform directory, but you don't have to match case when opening
|
||||||
it; any of the 16 obvious variations on open("FILe") work.
|
it; any of the 16 obvious variations on ``open("FILe")`` work.
|
||||||
|
|
||||||
NONE OF THAT IS CHANGING! Python will continue to follow platform
|
NONE OF THAT IS CHANGING! Python will continue to follow platform
|
||||||
conventions w.r.t. whether case is preserved when creating a file,
|
conventions w.r.t. whether case is preserved when creating a file,
|
||||||
and w.r.t. whether open() requires a case-sensitive match. In
|
and w.r.t. whether ``open()`` requires a case-sensitive match. In
|
||||||
practice, you should always code as if matches were
|
practice, you should always code as if matches were
|
||||||
case-sensitive, else your program won't be portable.
|
case-sensitive, else your program won't be portable.
|
||||||
|
|
||||||
What's proposed is to change the semantics of Python "import"
|
What's proposed is to change the semantics of Python "import"
|
||||||
statements, and there *only* in the lower left box.
|
statements, and there *only* in the lower left box.
|
||||||
|
|
||||||
|
|
||||||
Current Lower-Left Semantics
|
Current Lower-Left Semantics
|
||||||
|
============================
|
||||||
|
|
||||||
Support for MacOSX HFS+, and for Cygwin, is new in 2.1, so nothing
|
Support for MacOSX HFS+, and for Cygwin, is new in 2.1, so nothing
|
||||||
is changing there. What's changing is Windows behavior. Here are
|
is changing there. What's changing is Windows behavior. Here are
|
||||||
the current rules for import on Windows:
|
the current rules for import on Windows:
|
||||||
|
|
||||||
1. Despite that the filesystem is case-insensitive, Python insists
|
1. Despite that the filesystem is case-insensitive, Python insists
|
||||||
on a case-sensitive match. But not in the way the upper left
|
on a case-sensitive match. But not in the way the upper left
|
||||||
box works: if you have two files, FiLe.py and file.py on
|
box works: if you have two files, ``FiLe.py`` and ``file.py`` on
|
||||||
sys.path, and do
|
``sys.path``, and do::
|
||||||
|
|
||||||
import file
|
import file
|
||||||
|
|
||||||
then if Python finds FiLe.py first, it raises a NameError. It
|
then if Python finds ``FiLe.py`` first, it raises a ``NameError``. It
|
||||||
does *not* go on to find file.py; indeed, it's impossible to
|
does *not* go on to find ``file.py``; indeed, it's impossible to
|
||||||
import any but the first case-insensitive match on sys.path,
|
import any but the first case-insensitive match on ``sys.path``,
|
||||||
and then only if case matches exactly in the first
|
and then only if case matches exactly in the first
|
||||||
case-insensitive match.
|
case-insensitive match.
|
||||||
|
|
||||||
2. An ugly exception: if the first case-insensitive match on
|
2. An ugly exception: if the first case-insensitive match on
|
||||||
sys.path is for a file whose name is entirely in upper case
|
``sys.path`` is for a file whose name is entirely in upper case
|
||||||
(FILE.PY or FILE.PYC or FILE.PYO), then the import silently
|
(``FILE.PY`` or ``FILE.PYC`` or ``FILE.PYO``), then the import silently
|
||||||
grabs that, no matter what mixture of case was used in the
|
grabs that, no matter what mixture of case was used in the
|
||||||
import statement. This is apparently to cater to miserable old
|
import statement. This is apparently to cater to miserable old
|
||||||
filesystems that really fit in the lower right box. But this
|
filesystems that really fit in the lower right box. But this
|
||||||
exception is unique to Windows, for reasons that may or may not
|
exception is unique to Windows, for reasons that may or may not
|
||||||
exist.
|
exist.
|
||||||
|
|
||||||
3. And another exception: if the environment variable PYTHONCASEOK
|
3. And another exception: if the environment variable ``PYTHONCASEOK``
|
||||||
exists, Python silently grabs the first case-insensitive match
|
exists, Python silently grabs the first case-insensitive match
|
||||||
of any kind.
|
of any kind.
|
||||||
|
|
||||||
So these Windows rules are pretty complicated, and neither match
|
So these Windows rules are pretty complicated, and neither match
|
||||||
the Unix rules nor provide semantics natural for the native
|
the Unix rules nor provide semantics natural for the native
|
||||||
filesystem. That makes them hard to explain to Unix *or* Windows
|
filesystem. That makes them hard to explain to Unix *or* Windows
|
||||||
users. Nevertheless, they've worked fine for years, and in
|
users. Nevertheless, they've worked fine for years, and in
|
||||||
isolation there's no compelling reason to change them.
|
isolation there's no compelling reason to change them.
|
||||||
|
|
||||||
However, that was before the MacOSX HFS+ and Cygwin ports arrived.
|
However, that was before the MacOSX HFS+ and Cygwin ports arrived.
|
||||||
They also have case-preserving case-insensitive filesystems, but
|
They also have case-preserving case-insensitive filesystems, but
|
||||||
the people doing the ports despised the Windows rules. Indeed, a
|
the people doing the ports despised the Windows rules. Indeed, a
|
||||||
patch to make HFS+ act like Unix for imports got past a reviewer
|
patch to make HFS+ act like Unix for imports got past a reviewer
|
||||||
and into the code base, which incidentally made Cygwin also act
|
and into the code base, which incidentally made Cygwin also act
|
||||||
like Unix (but this met the unbounded approval of the Cygwin
|
like Unix (but this met the unbounded approval of the Cygwin
|
||||||
folks, so they sure didn't complain -- they had patches of their
|
folks, so they sure didn't complain -- they had patches of their
|
||||||
own pending to do this, but the reviewer for those balked).
|
own pending to do this, but the reviewer for those balked).
|
||||||
|
|
||||||
At a higher level, we want to keep Python consistent, by following
|
At a higher level, we want to keep Python consistent, by following
|
||||||
the same rules on *all* platforms with case-preserving
|
the same rules on *all* platforms with case-preserving
|
||||||
case-insensitive filesystems.
|
case-insensitive filesystems.
|
||||||
|
|
||||||
|
|
||||||
Proposed Semantics
|
Proposed Semantics
|
||||||
|
==================
|
||||||
|
|
||||||
The proposed new semantics for the lower left box:
|
The proposed new semantics for the lower left box:
|
||||||
|
|
||||||
A. If the PYTHONCASEOK environment variable exists, same as
|
A. If the ``PYTHONCASEOK`` environment variable exists, same as
|
||||||
before: silently accept the first case-insensitive match of any
|
before: silently accept the first case-insensitive match of any
|
||||||
kind; raise ImportError if none found.
|
kind; raise ImportError if none found.
|
||||||
|
|
||||||
B. Else search sys.path for the first case-sensitive match; raise
|
B. Else search ``sys.path`` for the first case-sensitive match; raise
|
||||||
ImportError if none found.
|
``ImportError`` if none found.
|
||||||
|
|
||||||
#B is the same rule as is used on Unix, so this will improve cross-
|
#B is the same rule as is used on Unix, so this will improve cross-
|
||||||
platform portability. That's good. #B is also the rule the Mac
|
platform portability. That's good. #B is also the rule the Mac
|
||||||
and Cygwin folks want (and wanted enough to implement themselves,
|
and Cygwin folks want (and wanted enough to implement themselves,
|
||||||
multiple times, which is a powerful argument in PythonLand). It
|
multiple times, which is a powerful argument in PythonLand). It
|
||||||
can't cause any existing non-exceptional Windows import to fail,
|
can't cause any existing non-exceptional Windows import to fail,
|
||||||
because any existing non-exceptional Windows import finds a
|
because any existing non-exceptional Windows import finds a
|
||||||
case-sensitive match first in the path -- and it still will. An
|
case-sensitive match first in the path -- and it still will. An
|
||||||
exceptional Windows import currently blows up with a NameError or
|
exceptional Windows import currently blows up with a ``NameError`` or
|
||||||
ImportError, in which latter case it still will, or in which
|
``ImportError``, in which latter case it still will, or in which
|
||||||
former case will continue searching, and either succeed or blow up
|
former case will continue searching, and either succeed or blow up
|
||||||
with an ImportError.
|
with an ``ImportError``.
|
||||||
|
|
||||||
#A is needed to cater to case-destroying filesystems mounted on Windows,
|
#A is needed to cater to case-destroying filesystems mounted on Windows,
|
||||||
and *may* also be used by people so enamored of "natural" Windows
|
and *may* also be used by people so enamored of "natural" Windows
|
||||||
behavior that they're willing to set an environment variable to
|
behavior that they're willing to set an environment variable to
|
||||||
get it. I don't intend to implement #A for Unix too, but that's
|
get it. I don't intend to implement #A for Unix too, but that's
|
||||||
just because I'm not clear on how I *could* do so efficiently (I'm
|
just because I'm not clear on how I *could* do so efficiently (I'm
|
||||||
not going to slow imports under Unix just for theoretical purity).
|
not going to slow imports under Unix just for theoretical purity).
|
||||||
|
|
||||||
The potential damage is here: #2 (matching on ALLCAPS.PY) is
|
The potential damage is here: #2 (matching on ``ALLCAPS.PY``) is
|
||||||
proposed to be dropped. Case-destroying filesystems are a
|
proposed to be dropped. Case-destroying filesystems are a
|
||||||
vanishing breed, and support for them is ugly. We're already
|
vanishing breed, and support for them is ugly. We're already
|
||||||
supporting (and will continue to support) PYTHONCASEOK for their
|
supporting (and will continue to support) ``PYTHONCASEOK`` for their
|
||||||
benefit, but they don't deserve multiple hacks in 2001.
|
benefit, but they don't deserve multiple hacks in 2001.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
End:
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
276
pep-0269.txt
276
pep-0269.txt
|
@ -5,184 +5,216 @@ Last-Modified: $Date$
|
||||||
Author: jriehl@spaceship.com (Jonathan Riehl)
|
Author: jriehl@spaceship.com (Jonathan Riehl)
|
||||||
Status: Deferred
|
Status: Deferred
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 24-Aug-2001
|
Created: 24-Aug-2001
|
||||||
Python-Version: 2.2
|
Python-Version: 2.2
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
Much like the parser module exposes the Python parser, this PEP
|
Much like the parser module exposes the Python parser, this PEP
|
||||||
proposes that the parser generator used to create the Python
|
proposes that the parser generator used to create the Python
|
||||||
parser, pgen, be exposed as a module in Python.
|
parser, ``pgen``, be exposed as a module in Python.
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
=========
|
||||||
|
|
||||||
Through the course of Pythonic history, there have been numerous
|
Through the course of Pythonic history, there have been numerous
|
||||||
discussions about the creation of a Python compiler [1]. These
|
discussions about the creation of a Python compiler [1]_. These
|
||||||
have resulted in several implementations of Python parsers, most
|
have resulted in several implementations of Python parsers, most
|
||||||
notably the parser module currently provided in the Python
|
notably the parser module currently provided in the Python
|
||||||
standard library[2] and Jeremy Hylton's compiler module[3].
|
standard library [2]_ and Jeremy Hylton's compiler module [3]_.
|
||||||
However, while multiple language changes have been proposed
|
However, while multiple language changes have been proposed
|
||||||
[4][5], experimentation with the Python syntax has lacked the
|
[4]_ [5]_, experimentation with the Python syntax has lacked the
|
||||||
benefit of a Python binding to the actual parser generator used to
|
benefit of a Python binding to the actual parser generator used to
|
||||||
build Python.
|
build Python.
|
||||||
|
|
||||||
By providing a Python wrapper analogous to Fred Drake Jr.'s parser
|
By providing a Python wrapper analogous to Fred Drake Jr.'s parser
|
||||||
wrapper, but targeted at the pgen library, the following
|
wrapper, but targeted at the ``pgen`` library, the following
|
||||||
assertions are made:
|
assertions are made:
|
||||||
|
|
||||||
1. Reference implementations of syntax changes will be easier to
|
1. Reference implementations of syntax changes will be easier to
|
||||||
develop. Currently, a reference implementation of a syntax
|
develop. Currently, a reference implementation of a syntax
|
||||||
change would require the developer to use the pgen tool from
|
change would require the developer to use the ``pgen`` tool from
|
||||||
the command line. The resulting parser data structure would
|
the command line. The resulting parser data structure would
|
||||||
then either have to be reworked to interface with a custom
|
then either have to be reworked to interface with a custom
|
||||||
CPython implementation, or wrapped as a C extension module.
|
CPython implementation, or wrapped as a C extension module.
|
||||||
|
|
||||||
2. Reference implementations of syntax changes will be easier to
|
2. Reference implementations of syntax changes will be easier to
|
||||||
distribute. Since the parser generator will be available in
|
distribute. Since the parser generator will be available in
|
||||||
Python, it should follow that the resulting parser will
|
Python, it should follow that the resulting parser will
|
||||||
accessible from Python. Therefore, reference implementations
|
accessible from Python. Therefore, reference implementations
|
||||||
should be available as pure Python code, versus using custom
|
should be available as pure Python code, versus using custom
|
||||||
versions of the existing CPython distribution, or as compilable
|
versions of the existing CPython distribution, or as compilable
|
||||||
extension modules.
|
extension modules.
|
||||||
|
|
||||||
3. Reference implementations of syntax changes will be easier to
|
3. Reference implementations of syntax changes will be easier to
|
||||||
discuss with a larger audience. This somewhat falls out of the
|
discuss with a larger audience. This somewhat falls out of the
|
||||||
second assertion, since the community of Python users is most
|
second assertion, since the community of Python users is most
|
||||||
likely larger than the community of CPython developers.
|
likely larger than the community of CPython developers.
|
||||||
|
|
||||||
4. Development of small languages in Python will be further
|
4. Development of small languages in Python will be further
|
||||||
enhanced, since the additional module will be a fully
|
enhanced, since the additional module will be a fully
|
||||||
functional LL(1) parser generator.
|
functional LL(1) parser generator.
|
||||||
|
|
||||||
|
|
||||||
Specification
|
Specification
|
||||||
|
=============
|
||||||
|
|
||||||
The proposed module will be called pgen. The pgen module will
|
The proposed module will be called ``pgen``. The ``pgen`` module will
|
||||||
contain the following functions:
|
contain the following functions:
|
||||||
|
|
||||||
parseGrammarFile (fileName) -> AST
|
|
||||||
The parseGrammarFile() function will read the file pointed to
|
|
||||||
by fileName and create an AST object. The AST nodes will
|
|
||||||
contain the nonterminal, numeric values of the parser
|
|
||||||
generator meta-grammar. The output AST will be an instance of
|
|
||||||
the AST extension class as provided by the parser module.
|
|
||||||
Syntax errors in the input file will cause the SyntaxError
|
|
||||||
exception to be raised.
|
|
||||||
|
|
||||||
parseGrammarString (text) -> AST
|
``parseGrammarFile (fileName) -> AST``
|
||||||
The parseGrammarString() function will follow the semantics of
|
--------------------------------------
|
||||||
the parseGrammarFile(), but accept the grammar text as a
|
|
||||||
string for input, as opposed to the file name.
|
|
||||||
|
|
||||||
buildParser (grammarAst) -> DFA
|
The ``parseGrammarFile()`` function will read the file pointed to
|
||||||
The buildParser() function will accept an AST object for input
|
by fileName and create an AST object. The AST nodes will
|
||||||
and return a DFA (deterministic finite automaton) data
|
contain the nonterminal, numeric values of the parser
|
||||||
structure. The DFA data structure will be a C extension
|
generator meta-grammar. The output AST will be an instance of
|
||||||
class, much like the AST structure is provided in the parser
|
the AST extension class as provided by the parser module.
|
||||||
module. If the input AST does not conform to the nonterminal
|
Syntax errors in the input file will cause the SyntaxError
|
||||||
codes defined for the pgen meta-grammar, buildParser() will
|
exception to be raised.
|
||||||
throw a ValueError exception.
|
|
||||||
|
|
||||||
parseFile (fileName, dfa, start) -> AST
|
|
||||||
The parseFile() function will essentially be a wrapper for the
|
|
||||||
PyParser_ParseFile() C API function. The wrapper code will
|
|
||||||
accept the DFA C extension class, and the file name. An AST
|
|
||||||
instance that conforms to the lexical values in the token
|
|
||||||
module and the nonterminal values contained in the DFA will be
|
|
||||||
output.
|
|
||||||
|
|
||||||
parseString (text, dfa, start) -> AST
|
``parseGrammarString (text) -> AST``
|
||||||
The parseString() function will operate in a similar fashion
|
------------------------------------
|
||||||
to the parseFile() function, but accept the parse text as an
|
|
||||||
argument. Much like parseFile() will wrap the
|
|
||||||
PyParser_ParseFile() C API function, parseString() will wrap
|
|
||||||
the PyParser_ParseString() function.
|
|
||||||
|
|
||||||
symbolToStringMap (dfa) -> dict
|
The ``parseGrammarString()`` function will follow the semantics of
|
||||||
The symbolToStringMap() function will accept a DFA instance
|
the ``parseGrammarFile()``, but accept the grammar text as a
|
||||||
and return a dictionary object that maps from the DFA's
|
string for input, as opposed to the file name.
|
||||||
numeric values for its nonterminals to the string names of the
|
|
||||||
nonterminals as found in the original grammar specification
|
|
||||||
for the DFA.
|
|
||||||
|
|
||||||
stringToSymbolMap (dfa) -> dict
|
|
||||||
The stringToSymbolMap() function output a dictionary mapping
|
|
||||||
the nonterminal names of the input DFA to their corresponding
|
|
||||||
numeric values.
|
|
||||||
|
|
||||||
Extra credit will be awarded if the map generation functions and
|
``buildParser (grammarAst) -> DFA``
|
||||||
parsing functions are also methods of the DFA extension class.
|
-----------------------------------
|
||||||
|
|
||||||
|
The ``buildParser()`` function will accept an AST object for input
|
||||||
|
and return a DFA (deterministic finite automaton) data
|
||||||
|
structure. The DFA data structure will be a C extension
|
||||||
|
class, much like the AST structure is provided in the parser
|
||||||
|
module. If the input AST does not conform to the nonterminal
|
||||||
|
codes defined for the ``pgen`` meta-grammar, ``buildParser()`` will
|
||||||
|
throw a ``ValueError`` exception.
|
||||||
|
|
||||||
|
|
||||||
|
``parseFile (fileName, dfa, start) -> AST``
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
The ``parseFile()`` function will essentially be a wrapper for the
|
||||||
|
``PyParser_ParseFile()`` C API function. The wrapper code will
|
||||||
|
accept the DFA C extension class, and the file name. An AST
|
||||||
|
instance that conforms to the lexical values in the token
|
||||||
|
module and the nonterminal values contained in the DFA will be
|
||||||
|
output.
|
||||||
|
|
||||||
|
|
||||||
|
``parseString (text, dfa, start) -> AST``
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
The ``parseString()`` function will operate in a similar fashion
|
||||||
|
to the ``parseFile()`` function, but accept the parse text as an
|
||||||
|
argument. Much like ``parseFile()`` will wrap the
|
||||||
|
``PyParser_ParseFile()`` C API function, ``parseString()`` will wrap
|
||||||
|
the ``PyParser_ParseString()`` function.
|
||||||
|
|
||||||
|
|
||||||
|
``symbolToStringMap (dfa) -> dict``
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
The ``symbolToStringMap()`` function will accept a DFA instance
|
||||||
|
and return a dictionary object that maps from the DFA's
|
||||||
|
numeric values for its nonterminals to the string names of the
|
||||||
|
nonterminals as found in the original grammar specification
|
||||||
|
for the DFA.
|
||||||
|
|
||||||
|
|
||||||
|
``stringToSymbolMap (dfa) -> dict``
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
The ``stringToSymbolMap()`` function output a dictionary mapping
|
||||||
|
the nonterminal names of the input DFA to their corresponding
|
||||||
|
numeric values.
|
||||||
|
|
||||||
|
|
||||||
|
Extra credit will be awarded if the map generation functions and
|
||||||
|
parsing functions are also methods of the DFA extension class.
|
||||||
|
|
||||||
|
|
||||||
Implementation Plan
|
Implementation Plan
|
||||||
|
===================
|
||||||
|
|
||||||
A cunning plan has been devised to accomplish this enhancement:
|
A cunning plan has been devised to accomplish this enhancement:
|
||||||
|
|
||||||
1. Rename the pgen functions to conform to the CPython naming
|
1. Rename the ``pgen`` functions to conform to the CPython naming
|
||||||
standards. This action may involve adding some header files to
|
standards. This action may involve adding some header files to
|
||||||
the Include subdirectory.
|
the Include subdirectory.
|
||||||
|
|
||||||
2. Move the pgen C modules in the Makefile.pre.in from unique pgen
|
2. Move the ``pgen`` C modules in the Makefile.pre.in from unique ``pgen``
|
||||||
elements to the Python C library.
|
elements to the Python C library.
|
||||||
|
|
||||||
3. Make any needed changes to the parser module so the AST
|
3. Make any needed changes to the parser module so the AST
|
||||||
extension class understands that there are AST types it may not
|
extension class understands that there are AST types it may not
|
||||||
understand. Cursory examination of the AST extension class
|
understand. Cursory examination of the AST extension class
|
||||||
shows that it keeps track of whether the tree is a suite or an
|
shows that it keeps track of whether the tree is a suite or an
|
||||||
expression.
|
expression.
|
||||||
|
|
||||||
3. Code an additional C module in the Modules directory. The C
|
3. Code an additional C module in the Modules directory. The C
|
||||||
extension module will implement the DFA extension class and the
|
extension module will implement the DFA extension class and the
|
||||||
functions outlined in the previous section.
|
functions outlined in the previous section.
|
||||||
|
|
||||||
4. Add the new module to the build process. Black magic, indeed.
|
4. Add the new module to the build process. Black magic, indeed.
|
||||||
|
|
||||||
|
|
||||||
Limitations
|
Limitations
|
||||||
|
===========
|
||||||
|
|
||||||
Under this proposal, would be designers of Python 3000 will still
|
Under this proposal, would be designers of Python 3000 will still
|
||||||
be constrained to Python's lexical conventions. The addition,
|
be constrained to Python's lexical conventions. The addition,
|
||||||
subtraction or modification of the Python lexer is outside the
|
subtraction or modification of the Python lexer is outside the
|
||||||
scope of this PEP.
|
scope of this PEP.
|
||||||
|
|
||||||
|
|
||||||
Reference Implementation
|
Reference Implementation
|
||||||
|
========================
|
||||||
|
|
||||||
No reference implementation is currently provided. A patch
|
No reference implementation is currently provided. A patch
|
||||||
was provided at some point in
|
was provided at some point in
|
||||||
http://sourceforge.net/tracker/index.php?func=detail&aid=599331&group_id=5470&atid=305470
|
http://sourceforge.net/tracker/index.php?func=detail&aid=599331&group_id=5470&atid=305470
|
||||||
but that patch is no longer maintained.
|
but that patch is no longer maintained.
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
[1] The (defunct) Python Compiler-SIG
|
.. [1] The (defunct) Python Compiler-SIG
|
||||||
http://www.python.org/sigs/compiler-sig/
|
http://www.python.org/sigs/compiler-sig/
|
||||||
|
|
||||||
[2] Parser Module Documentation
|
.. [2] Parser Module Documentation
|
||||||
http://docs.python.org/library/parser.html
|
http://docs.python.org/library/parser.html
|
||||||
|
|
||||||
[3] Hylton, Jeremy.
|
.. [3] Hylton, Jeremy.
|
||||||
http://docs.python.org/library/compiler.html
|
http://docs.python.org/library/compiler.html
|
||||||
|
|
||||||
[4] Pelletier, Michel. "Python Interface Syntax", PEP-245.
|
.. [4] Pelletier, Michel. "Python Interface Syntax", PEP-245.
|
||||||
http://www.python.org/dev/peps/pep-0245/
|
http://www.python.org/dev/peps/pep-0245/
|
||||||
|
|
||||||
[5] The Python Types-SIG
|
.. [5] The Python Types-SIG
|
||||||
http://www.python.org/sigs/types-sig/
|
http://www.python.org/sigs/types-sig/
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
fill-column: 70
|
indent-tabs-mode: nil
|
||||||
End:
|
fill-column: 70
|
||||||
|
End:
|
||||||
|
|
213
pep-0288.txt
213
pep-0288.txt
|
@ -5,159 +5,168 @@ Last-Modified: $Date$
|
||||||
Author: python@rcn.com (Raymond Hettinger)
|
Author: python@rcn.com (Raymond Hettinger)
|
||||||
Status: Withdrawn
|
Status: Withdrawn
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
|
Content-Type: text/x-rst
|
||||||
Created: 21-Mar-2002
|
Created: 21-Mar-2002
|
||||||
Python-Version: 2.5
|
Python-Version: 2.5
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
This PEP proposes to enhance generators by providing mechanisms for
|
This PEP proposes to enhance generators by providing mechanisms for
|
||||||
raising exceptions and sharing data with running generators.
|
raising exceptions and sharing data with running generators.
|
||||||
|
|
||||||
|
|
||||||
Status
|
Status
|
||||||
|
======
|
||||||
|
|
||||||
This PEP is withdrawn. The exception raising mechanism was extended
|
This PEP is withdrawn. The exception raising mechanism was extended
|
||||||
and subsumed into PEP 343. The attribute passing capability
|
and subsumed into PEP 343. The attribute passing capability
|
||||||
never built a following, did not have a clear implementation,
|
never built a following, did not have a clear implementation,
|
||||||
and did not have a clean way for the running generator to access
|
and did not have a clean way for the running generator to access
|
||||||
its own namespace.
|
its own namespace.
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
=========
|
||||||
|
|
||||||
Currently, only class based iterators can provide attributes and
|
Currently, only class based iterators can provide attributes and
|
||||||
exception handling. However, class based iterators are harder to
|
exception handling. However, class based iterators are harder to
|
||||||
write, less compact, less readable, and slower. A better solution
|
write, less compact, less readable, and slower. A better solution
|
||||||
is to enable these capabilities for generators.
|
is to enable these capabilities for generators.
|
||||||
|
|
||||||
Enabling attribute assignments allows data to be passed to and from
|
Enabling attribute assignments allows data to be passed to and from
|
||||||
running generators. The approach of sharing data using attributes
|
running generators. The approach of sharing data using attributes
|
||||||
pervades Python. Other approaches exist but are somewhat hackish
|
pervades Python. Other approaches exist but are somewhat hackish
|
||||||
in comparison.
|
in comparison.
|
||||||
|
|
||||||
Another evolutionary step is to add a generator method to allow
|
Another evolutionary step is to add a generator method to allow
|
||||||
exceptions to be passed to a generator. Currently, there is no
|
exceptions to be passed to a generator. Currently, there is no
|
||||||
clean method for triggering exceptions from outside the generator.
|
clean method for triggering exceptions from outside the generator.
|
||||||
Also, generator exception passing helps mitigate the try/finally
|
Also, generator exception passing helps mitigate the try/finally
|
||||||
prohibition for generators. The need is especially acute for
|
prohibition for generators. The need is especially acute for
|
||||||
generators needing to flush buffers or close resources upon termination.
|
generators needing to flush buffers or close resources upon termination.
|
||||||
|
|
||||||
The two proposals are backwards compatible and require no new
|
The two proposals are backwards compatible and require no new
|
||||||
keywords. They are being recommended for Python version 2.5.
|
keywords. They are being recommended for Python version 2.5.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Specification for Generator Attributes
|
Specification for Generator Attributes
|
||||||
|
======================================
|
||||||
|
|
||||||
Essentially, the proposal is to emulate attribute writing for classes.
|
Essentially, the proposal is to emulate attribute writing for classes.
|
||||||
The only wrinkle is that generators lack a way to refer to instances of
|
The only wrinkle is that generators lack a way to refer to instances of
|
||||||
themselves. So, the proposal is to provide a function for discovering
|
themselves. So, the proposal is to provide a function for discovering
|
||||||
the reference. For example:
|
the reference. For example::
|
||||||
|
|
||||||
def mygen(filename):
|
def mygen(filename):
|
||||||
self = sys.get_generator()
|
self = sys.get_generator()
|
||||||
myfile = open(filename)
|
myfile = open(filename)
|
||||||
for line in myfile:
|
for line in myfile:
|
||||||
if len(line) < 10:
|
if len(line) < 10:
|
||||||
continue
|
continue
|
||||||
self.pos = myfile.tell()
|
self.pos = myfile.tell()
|
||||||
yield line.upper()
|
yield line.upper()
|
||||||
|
|
||||||
g = mygen('sample.txt')
|
g = mygen('sample.txt')
|
||||||
line1 = g.next()
|
line1 = g.next()
|
||||||
print 'Position', g.pos
|
print 'Position', g.pos
|
||||||
|
|
||||||
Uses for generator attributes include:
|
Uses for generator attributes include:
|
||||||
|
|
||||||
1. Providing generator clients with extra information (as shown
|
1. Providing generator clients with extra information (as shown
|
||||||
above).
|
above).
|
||||||
2. Externally setting control flags governing generator operation
|
2. Externally setting control flags governing generator operation
|
||||||
(possibly telling a generator when to step in or step over
|
(possibly telling a generator when to step in or step over
|
||||||
data groups).
|
data groups).
|
||||||
3. Writing lazy consumers with complex execution states
|
3. Writing lazy consumers with complex execution states
|
||||||
(an arithmetic encoder output stream for example).
|
(an arithmetic encoder output stream for example).
|
||||||
4. Writing co-routines (as demonstrated in Dr. Mertz's articles [1]).
|
4. Writing co-routines (as demonstrated in Dr. Mertz's articles [1]_).
|
||||||
|
|
||||||
The control flow of 'yield' and 'next' is unchanged by this
|
The control flow of 'yield' and 'next' is unchanged by this
|
||||||
proposal. The only change is that data can passed to and from the
|
proposal. The only change is that data can passed to and from the
|
||||||
generator. Most of the underlying machinery is already in place,
|
generator. Most of the underlying machinery is already in place,
|
||||||
only the access function needs to be added.
|
only the access function needs to be added.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Specification for Generator Exception Passing:
|
Specification for Generator Exception Passing
|
||||||
|
=============================================
|
||||||
|
|
||||||
Add a .throw(exception) method to the generator interface:
|
Add a .throw(exception) method to the generator interface::
|
||||||
|
|
||||||
def logger():
|
def logger():
|
||||||
start = time.time()
|
start = time.time()
|
||||||
log = []
|
log = []
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
log.append(time.time() - start)
|
log.append(time.time() - start)
|
||||||
yield log[-1]
|
yield log[-1]
|
||||||
except WriteLog:
|
except WriteLog:
|
||||||
writelog(log)
|
writelog(log)
|
||||||
|
|
||||||
g = logger()
|
g = logger()
|
||||||
for i in [10,20,40,80,160]:
|
for i in [10,20,40,80,160]:
|
||||||
testsuite(i)
|
testsuite(i)
|
||||||
g.next()
|
g.next()
|
||||||
g.throw(WriteLog)
|
g.throw(WriteLog)
|
||||||
|
|
||||||
There is no existing work-around for triggering an exception
|
There is no existing work-around for triggering an exception
|
||||||
inside a generator. It is the only case in Python where active
|
inside a generator. It is the only case in Python where active
|
||||||
code cannot be excepted to or through.
|
code cannot be excepted to or through.
|
||||||
|
|
||||||
Generator exception passing also helps address an intrinsic
|
Generator exception passing also helps address an intrinsic
|
||||||
limitation on generators, the prohibition against their using
|
limitation on generators, the prohibition against their using
|
||||||
try/finally to trigger clean-up code [2].
|
try/finally to trigger clean-up code [2]_.
|
||||||
|
|
||||||
Note A: The name of the throw method was selected for several
|
Note A: The name of the throw method was selected for several
|
||||||
reasons. Raise is a keyword and so cannot be used as a method
|
reasons. Raise is a keyword and so cannot be used as a method
|
||||||
name. Unlike raise which immediately raises an exception from the
|
name. Unlike raise which immediately raises an exception from the
|
||||||
current execution point, throw will first return to the generator
|
current execution point, throw will first return to the generator
|
||||||
and then raise the exception. The word throw is suggestive of
|
and then raise the exception. The word throw is suggestive of
|
||||||
putting the exception in another location. The word throw is
|
putting the exception in another location. The word throw is
|
||||||
already associated with exceptions in other languages.
|
already associated with exceptions in other languages.
|
||||||
|
|
||||||
Alternative method names were considered: resolve(), signal(),
|
Alternative method names were considered: ``resolve()``, ``signal()``,
|
||||||
genraise(), raiseinto(), and flush(). None of these fit as well
|
``genraise()``, ``raiseinto()``, and ``flush()``. None of these fit as well
|
||||||
as throw().
|
as ``throw()``.
|
||||||
|
|
||||||
Note B: To keep the throw() syntax simple only the instance
|
Note B: To keep the ``throw()`` syntax simple only the instance
|
||||||
version of the raise syntax would be supported (no variants for
|
version of the raise syntax would be supported (no variants for
|
||||||
"raise string" or "raise class, instance").
|
"raise string" or "raise class, instance").
|
||||||
|
|
||||||
Calling "g.throw(instance)" would correspond to writing
|
Calling ``g.throw(instance)`` would correspond to writing
|
||||||
"raise instance" immediately after the most recent yield.
|
``raise instance`` immediately after the most recent yield.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
References
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
[1] Dr. David Mertz's draft columns for Charming Python:
|
.. [1] Dr. David Mertz's draft columns for Charming Python
|
||||||
http://gnosis.cx/publish/programming/charming_python_b5.txt
|
http://gnosis.cx/publish/programming/charming_python_b5.txt
|
||||||
http://gnosis.cx/publish/programming/charming_python_b7.txt
|
http://gnosis.cx/publish/programming/charming_python_b7.txt
|
||||||
|
|
||||||
[2] PEP 255 Simple Generators:
|
.. [2] PEP 255 Simple Generators
|
||||||
http://www.python.org/dev/peps/pep-0255/
|
http://www.python.org/dev/peps/pep-0255/
|
||||||
|
|
||||||
[3] Proof-of-concept recipe:
|
.. [3] Proof-of-concept recipe
|
||||||
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/164044
|
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/164044
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
fill-column: 70
|
indent-tabs-mode: nil
|
||||||
End:
|
fill-column: 70
|
||||||
|
End:
|
||||||
|
|
240
pep-0312.txt
240
pep-0312.txt
|
@ -5,181 +5,205 @@ Last-Modified: $Date$
|
||||||
Author: Roman Suzi <rnd@onego.ru>, Alex Martelli <aleaxit@gmail.com>
|
Author: Roman Suzi <rnd@onego.ru>, Alex Martelli <aleaxit@gmail.com>
|
||||||
Status: Deferred
|
Status: Deferred
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
Content-Type: text/plain
|
Content-Type: text/x-rst
|
||||||
Created: 11-Feb-2003
|
Created: 11-Feb-2003
|
||||||
Python-Version: 2.4
|
Python-Version: 2.4
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
|
This PEP proposes to make argumentless lambda keyword optional in
|
||||||
|
some cases where it is not grammatically ambiguous.
|
||||||
|
|
||||||
This PEP proposes to make argumentless lambda keyword optional in
|
|
||||||
some cases where it is not grammatically ambiguous.
|
|
||||||
|
|
||||||
Deferral
|
Deferral
|
||||||
|
========
|
||||||
|
|
||||||
The BDFL hates the unary colon syntax. This PEP needs to go back
|
The BDFL hates the unary colon syntax. This PEP needs to go back
|
||||||
to the drawing board and find a more Pythonic syntax (perhaps an
|
to the drawing board and find a more Pythonic syntax (perhaps an
|
||||||
alternative unary operator). See python-dev discussion on
|
alternative unary operator). See python-dev discussion on
|
||||||
17 June 2005.
|
17 June 2005 [1]_.
|
||||||
|
|
||||||
|
Also, it is probably a good idea to eliminate the alternative
|
||||||
|
propositions which have no chance at all. The examples section
|
||||||
|
is good and highlights the readability improvements. It would
|
||||||
|
carry more weight with additional examples and with real-world
|
||||||
|
referents (instead of the abstracted dummy calls to ``:A`` and ``:B``).
|
||||||
|
|
||||||
Also, it is probably a good idea to eliminate the alternative
|
|
||||||
propositions which have no chance at all. The examples section
|
|
||||||
is good and highlights the readability improvements. It would
|
|
||||||
carry more weight with additional examples and with real-world
|
|
||||||
referents (instead of the abstracted dummy calls to :A and :B).
|
|
||||||
|
|
||||||
Motivation
|
Motivation
|
||||||
|
==========
|
||||||
|
|
||||||
Lambdas are useful for defining anonymous functions, e.g. for use
|
Lambdas are useful for defining anonymous functions, e.g. for use
|
||||||
as callbacks or (pseudo)-lazy evaluation schemes. Often, lambdas
|
as callbacks or (pseudo)-lazy evaluation schemes. Often, lambdas
|
||||||
are not used when they would be appropriate, just because the
|
are not used when they would be appropriate, just because the
|
||||||
keyword "lambda" makes code look complex. Omitting lambda in some
|
keyword "lambda" makes code look complex. Omitting lambda in some
|
||||||
special cases is possible, with small and backwards compatible
|
special cases is possible, with small and backwards compatible
|
||||||
changes to the grammar, and provides a cheap cure against such
|
changes to the grammar, and provides a cheap cure against such
|
||||||
"lambdaphobia".
|
"lambdaphobia".
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
=========
|
||||||
|
|
||||||
Sometimes people do not use lambdas because they fear to introduce
|
Sometimes people do not use lambdas because they fear to introduce
|
||||||
a term with a theory behind it. This proposal makes introducing
|
a term with a theory behind it. This proposal makes introducing
|
||||||
argumentless lambdas easier, by omitting the "lambda" keyword.
|
argumentless lambdas easier, by omitting the "lambda" keyword.
|
||||||
itself. Implementation can be done simply changing grammar so it
|
itself. Implementation can be done simply changing grammar so it
|
||||||
lets the "lambda" keyword be implied in a few well-known cases.
|
lets the "lambda" keyword be implied in a few well-known cases.
|
||||||
In particular, adding surrounding brackets lets you specify
|
In particular, adding surrounding brackets lets you specify
|
||||||
nullary lambda anywhere.
|
nullary lambda anywhere.
|
||||||
|
|
||||||
|
|
||||||
Syntax
|
Syntax
|
||||||
|
======
|
||||||
|
|
||||||
An argumentless "lambda" keyword can be omitted in the following
|
An argumentless "lambda" keyword can be omitted in the following
|
||||||
cases:
|
cases:
|
||||||
|
|
||||||
* immediately after "=" in named parameter assignment or default
|
* immediately after "=" in named parameter assignment or default
|
||||||
value assignment;
|
value assignment;
|
||||||
|
|
||||||
* immediately after "(" in any expression;
|
* immediately after "(" in any expression;
|
||||||
|
|
||||||
* immediately after a "," in a function argument list;
|
* immediately after a "," in a function argument list;
|
||||||
|
|
||||||
* immediately after a ":" in a dictionary literal; (not
|
* immediately after a ":" in a dictionary literal; (not
|
||||||
implemented)
|
implemented)
|
||||||
|
|
||||||
* in an assignment statement; (not implemented)
|
* in an assignment statement; (not implemented)
|
||||||
|
|
||||||
|
|
||||||
Examples of Use
|
Examples of Use
|
||||||
|
===============
|
||||||
|
|
||||||
1) Inline "if":
|
1) Inline ``if``::
|
||||||
|
|
||||||
def ifelse(cond, true_part, false_part):
|
def ifelse(cond, true_part, false_part):
|
||||||
if cond:
|
if cond:
|
||||||
return true_part()
|
return true_part()
|
||||||
else:
|
else:
|
||||||
return false_part()
|
return false_part()
|
||||||
|
|
||||||
# old syntax:
|
# old syntax:
|
||||||
print ifelse(a < b, lambda:A, lambda:B)
|
print ifelse(a < b, lambda:A, lambda:B)
|
||||||
|
|
||||||
# new syntax:
|
# new syntax:
|
||||||
print ifelse(a < b, :A, :B)
|
print ifelse(a < b, :A, :B)
|
||||||
|
|
||||||
# parts A and B may require extensive processing, as in:
|
# parts A and B may require extensive processing, as in:
|
||||||
print ifelse(a < b, :ext_proc1(A), :ext_proc2(B))
|
print ifelse(a < b, :ext_proc1(A), :ext_proc2(B))
|
||||||
|
|
||||||
2) Locking:
|
2) Locking::
|
||||||
|
|
||||||
def with(alock, acallable):
|
def with(alock, acallable):
|
||||||
alock.acquire()
|
alock.acquire()
|
||||||
try:
|
try:
|
||||||
acallable()
|
acallable()
|
||||||
finally:
|
finally:
|
||||||
alock.release()
|
alock.release()
|
||||||
|
|
||||||
with(mylock, :x(y(), 23, z(), 'foo'))
|
with(mylock, :x(y(), 23, z(), 'foo'))
|
||||||
|
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
==============
|
||||||
|
|
||||||
Implementation requires some tweaking of the Grammar/Grammar file
|
Implementation requires some tweaking of the Grammar/Grammar file
|
||||||
in the Python sources, and some adjustment of
|
in the Python sources, and some adjustment of
|
||||||
Modules/parsermodule.c to make syntactic and pragmatic changes.
|
Modules/parsermodule.c to make syntactic and pragmatic changes.
|
||||||
|
|
||||||
(Some grammar/parser guru is needed to make a full
|
(Some grammar/parser guru is needed to make a full
|
||||||
implementation.)
|
implementation.)
|
||||||
|
|
||||||
Here are the changes needed to Grammar to allow implicit lambda:
|
Here are the changes needed to Grammar to allow implicit lambda::
|
||||||
|
|
||||||
varargslist: (fpdef ['=' imptest] ',')* ('*' NAME [',' '**'
|
varargslist: (fpdef ['=' imptest] ',')* ('*' NAME [',' '**'
|
||||||
NAME] | '**' NAME) | fpdef ['=' imptest] (',' fpdef ['='
|
NAME] | '**' NAME) | fpdef ['=' imptest] (',' fpdef ['='
|
||||||
imptest])* [',']
|
imptest])* [',']
|
||||||
|
|
||||||
imptest: test | implambdef
|
imptest: test | implambdef
|
||||||
|
|
||||||
atom: '(' [imptestlist] ')' | '[' [listmaker] ']' |
|
atom: '(' [imptestlist] ')' | '[' [listmaker] ']' |
|
||||||
'{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+
|
'{' [dictmaker] '}' | '`' testlist1 '`' | NAME | NUMBER | STRING+
|
||||||
|
|
||||||
implambdef: ':' test
|
implambdef: ':' test
|
||||||
|
|
||||||
imptestlist: imptest (',' imptest)* [',']
|
imptestlist: imptest (',' imptest)* [',']
|
||||||
|
|
||||||
argument: [test '='] imptest
|
argument: [test '='] imptest
|
||||||
|
|
||||||
Three new non-terminals are needed: imptest for the place where
|
Three new non-terminals are needed: ``imptest`` for the place where
|
||||||
implicit lambda may occur, implambdef for the implicit lambda
|
implicit lambda may occur, ``implambdef`` for the implicit lambda
|
||||||
definition itself, imptestlist for a place where imptest's may
|
definition itself, ``imptestlist`` for a place where ``imptest``'s may
|
||||||
occur.
|
occur.
|
||||||
|
|
||||||
This implementation is not complete. First, because some files in
|
This implementation is not complete. First, because some files in
|
||||||
Parser module need to be updated. Second, some additional places
|
Parser module need to be updated. Second, some additional places
|
||||||
aren't implemented, see Syntax section above.
|
aren't implemented, see Syntax section above.
|
||||||
|
|
||||||
|
|
||||||
Discussion
|
Discussion
|
||||||
|
==========
|
||||||
|
|
||||||
This feature is not a high-visibility one (the only novel part is
|
This feature is not a high-visibility one (the only novel part is
|
||||||
the absence of lambda). The feature is intended to make null-ary
|
the absence of lambda). The feature is intended to make null-ary
|
||||||
lambdas more appealing syntactically, to provide lazy evaluation
|
lambdas more appealing syntactically, to provide lazy evaluation
|
||||||
of expressions in some simple cases. This proposal is not targeted
|
of expressions in some simple cases. This proposal is not targeted
|
||||||
at more advanced cases (demanding arguments for the lambda).
|
at more advanced cases (demanding arguments for the lambda).
|
||||||
|
|
||||||
There is an alternative proposition for implicit lambda: implicit
|
There is an alternative proposition for implicit lambda: implicit
|
||||||
lambda with unused arguments. In this case the function defined by
|
lambda with unused arguments. In this case the function defined by
|
||||||
such lambda can accept any parameters, i.e. be equivalent to:
|
such lambda can accept any parameters, i.e. be equivalent to:
|
||||||
lambda *args: expr. This form would be more powerful. Grep in the
|
``lambda *args: expr``. This form would be more powerful. Grep in the
|
||||||
standard library revealed that such lambdas are indeed in use.
|
standard library revealed that such lambdas are indeed in use.
|
||||||
|
|
||||||
One more extension can provide a way to have a list of parameters
|
One more extension can provide a way to have a list of parameters
|
||||||
passed to a function defined by implicit lambda. However, such
|
passed to a function defined by implicit lambda. However, such
|
||||||
parameters need some special name to be accessed and are unlikely
|
parameters need some special name to be accessed and are unlikely
|
||||||
to be included in the language. Possible local names for such
|
to be included in the language. Possible local names for such
|
||||||
parameters are: _, __args__, __. For example:
|
parameters are: ``_``, ``__args__``, ``__``. For example::
|
||||||
|
|
||||||
reduce(:_[0] + _[1], [1,2,3], 0)
|
reduce(:_[0] + _[1], [1,2,3], 0)
|
||||||
reduce(:__[0] + __[1], [1,2,3], 0)
|
reduce(:__[0] + __[1], [1,2,3], 0)
|
||||||
reduce(:__args__[0] + __args__[1], [1,2,3], 0)
|
reduce(:__args__[0] + __args__[1], [1,2,3], 0)
|
||||||
|
|
||||||
These forms do not look very nice, and in the PEP author's opinion
|
These forms do not look very nice, and in the PEP author's opinion
|
||||||
do not justify the removal of the lambda keyword in such cases.
|
do not justify the removal of the lambda keyword in such cases.
|
||||||
|
|
||||||
|
|
||||||
Credits
|
Credits
|
||||||
|
=======
|
||||||
|
|
||||||
|
The idea of dropping lambda was first coined by Paul Rubin at 08
|
||||||
|
Feb 2003 16:39:30 -0800 in comp.lang.python while discussing the
|
||||||
|
thread "For review: PEP 308 - If-then-else expression" [2]_.
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [1] Guido van Rossum, Recommend accepting PEP 312 -- Simple Implicit Lambda
|
||||||
|
https://mail.python.org/pipermail/python-dev/2005-June/054304.html
|
||||||
|
|
||||||
|
.. [2] Guido van Rossum, For review: PEP 308 - If-then-else expression
|
||||||
|
https://mail.python.org/pipermail/python-dev/2003-February/033178.html
|
||||||
|
|
||||||
The idea of dropping lambda was first coined by Paul Rubin at 08
|
|
||||||
Feb 2003 16:39:30 -0800 in comp.lang.python while discussing the
|
|
||||||
thread "For review: PEP 308 - If-then-else expression".
|
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
sentence-end-double-space: t
|
indent-tabs-mode: nil
|
||||||
fill-column: 70
|
sentence-end-double-space: t
|
||||||
End:
|
fill-column: 70
|
||||||
|
End:
|
||||||
|
|
202
pep-0315.txt
202
pep-0315.txt
|
@ -2,160 +2,176 @@ PEP: 315
|
||||||
Title: Enhanced While Loop
|
Title: Enhanced While Loop
|
||||||
Version: $Revision$
|
Version: $Revision$
|
||||||
Last-Modified: $Date$
|
Last-Modified: $Date$
|
||||||
Author: Raymond Hettinger <python@rcn.com>
|
Author: Raymond Hettinger <python@rcn.com>, W Isaac Carroll <icarroll@pobox.com>
|
||||||
W Isaac Carroll <icarroll@pobox.com>
|
|
||||||
Status: Rejected
|
Status: Rejected
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
Content-Type: text/plain
|
Content-Type: text/x-rst
|
||||||
Created: 25-Apr-2003
|
Created: 25-Apr-2003
|
||||||
Python-Version: 2.5
|
Python-Version: 2.5
|
||||||
Post-History:
|
Post-History:
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
This PEP proposes adding an optional "do" clause to the beginning
|
This PEP proposes adding an optional "do" clause to the beginning
|
||||||
of the while loop to make loop code clearer and reduce errors
|
of the while loop to make loop code clearer and reduce errors
|
||||||
caused by code duplication.
|
caused by code duplication.
|
||||||
|
|
||||||
|
|
||||||
Notice
|
Notice
|
||||||
|
======
|
||||||
|
|
||||||
Rejected; see
|
Rejected; see [1]_.
|
||||||
http://mail.python.org/pipermail/python-ideas/2013-June/021610.html
|
|
||||||
|
|
||||||
This PEP has been deferred since 2006; see
|
This PEP has been deferred since 2006; see [2]_.
|
||||||
http://mail.python.org/pipermail/python-dev/2006-February/060718.html
|
|
||||||
|
|
||||||
Subsequent efforts to revive the PEP in April 2009 did not
|
Subsequent efforts to revive the PEP in April 2009 did not
|
||||||
meet with success because no syntax emerged that could
|
meet with success because no syntax emerged that could
|
||||||
compete with the following form:
|
compete with the following form::
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
<setup code>
|
<setup code>
|
||||||
if not <condition>:
|
if not <condition>:
|
||||||
break
|
break
|
||||||
<loop body>
|
<loop body>
|
||||||
|
|
||||||
A syntax alternative to the one proposed in the PEP was found for
|
A syntax alternative to the one proposed in the PEP was found for
|
||||||
a basic do-while loop but it gained little support because the
|
a basic do-while loop but it gained little support because the
|
||||||
condition was at the top:
|
condition was at the top::
|
||||||
|
|
||||||
do ... while <cond>:
|
do ... while <cond>:
|
||||||
<loop body>
|
<loop body>
|
||||||
|
|
||||||
Users of the language are advised to use the while-True form with
|
Users of the language are advised to use the while-True form with
|
||||||
an inner if-break when a do-while loop would have been appropriate.
|
an inner if-break when a do-while loop would have been appropriate.
|
||||||
|
|
||||||
|
|
||||||
Motivation
|
Motivation
|
||||||
|
==========
|
||||||
|
|
||||||
It is often necessary for some code to be executed before each
|
It is often necessary for some code to be executed before each
|
||||||
evaluation of the while loop condition. This code is often
|
evaluation of the while loop condition. This code is often
|
||||||
duplicated outside the loop, as setup code that executes once
|
duplicated outside the loop, as setup code that executes once
|
||||||
before entering the loop:
|
before entering the loop::
|
||||||
|
|
||||||
|
<setup code>
|
||||||
|
while <condition>:
|
||||||
|
<loop body>
|
||||||
<setup code>
|
<setup code>
|
||||||
while <condition>:
|
|
||||||
<loop body>
|
|
||||||
<setup code>
|
|
||||||
|
|
||||||
The problem is that duplicated code can be a source of errors if
|
The problem is that duplicated code can be a source of errors if
|
||||||
one instance is changed but the other is not. Also, the purpose
|
one instance is changed but the other is not. Also, the purpose
|
||||||
of the second instance of the setup code is not clear because it
|
of the second instance of the setup code is not clear because it
|
||||||
comes at the end of the loop.
|
comes at the end of the loop.
|
||||||
|
|
||||||
It is possible to prevent code duplication by moving the loop
|
It is possible to prevent code duplication by moving the loop
|
||||||
condition into a helper function, or an if statement in the loop
|
condition into a helper function, or an if statement in the loop
|
||||||
body. However, separating the loop condition from the while
|
body. However, separating the loop condition from the while
|
||||||
keyword makes the behavior of the loop less clear:
|
keyword makes the behavior of the loop less clear::
|
||||||
|
|
||||||
def helper(args):
|
def helper(args):
|
||||||
<setup code>
|
<setup code>
|
||||||
return <condition>
|
return <condition>
|
||||||
|
|
||||||
while helper(args):
|
while helper(args):
|
||||||
<loop body>
|
<loop body>
|
||||||
|
|
||||||
This last form has the additional drawback of requiring the loop's
|
This last form has the additional drawback of requiring the loop's
|
||||||
else clause to be added to the body of the if statement, further
|
else clause to be added to the body of the if statement, further
|
||||||
obscuring the loop's behavior:
|
obscuring the loop's behavior::
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
<setup code>
|
<setup code>
|
||||||
if not <condition>: break
|
if not <condition>: break
|
||||||
<loop body>
|
<loop body>
|
||||||
|
|
||||||
This PEP proposes to solve these problems by adding an optional
|
This PEP proposes to solve these problems by adding an optional
|
||||||
clause to the while loop, which allows the setup code to be
|
clause to the while loop, which allows the setup code to be
|
||||||
expressed in a natural way:
|
expressed in a natural way::
|
||||||
|
|
||||||
do:
|
do:
|
||||||
<setup code>
|
<setup code>
|
||||||
while <condition>:
|
while <condition>:
|
||||||
<loop body>
|
<loop body>
|
||||||
|
|
||||||
This keeps the loop condition with the while keyword where it
|
This keeps the loop condition with the while keyword where it
|
||||||
belongs, and does not require code to be duplicated.
|
belongs, and does not require code to be duplicated.
|
||||||
|
|
||||||
|
|
||||||
Syntax
|
Syntax
|
||||||
|
======
|
||||||
|
|
||||||
The syntax of the while statement
|
The syntax of the while statement::
|
||||||
|
|
||||||
while_stmt : "while" expression ":" suite
|
while_stmt : "while" expression ":" suite
|
||||||
["else" ":" suite]
|
["else" ":" suite]
|
||||||
|
|
||||||
is extended as follows:
|
is extended as follows::
|
||||||
|
|
||||||
while_stmt : ["do" ":" suite]
|
while_stmt : ["do" ":" suite]
|
||||||
"while" expression ":" suite
|
"while" expression ":" suite
|
||||||
["else" ":" suite]
|
["else" ":" suite]
|
||||||
|
|
||||||
|
|
||||||
Semantics of break and continue
|
Semantics of break and continue
|
||||||
|
===============================
|
||||||
|
|
||||||
In the do-while loop the break statement will behave the same as
|
In the do-while loop the break statement will behave the same as
|
||||||
in the standard while loop: It will immediately terminate the loop
|
in the standard while loop: It will immediately terminate the loop
|
||||||
without evaluating the loop condition or executing the else
|
without evaluating the loop condition or executing the else
|
||||||
clause.
|
clause.
|
||||||
|
|
||||||
A continue statement in the do-while loop jumps to the while
|
A continue statement in the do-while loop jumps to the while
|
||||||
condition check.
|
condition check.
|
||||||
|
|
||||||
In general, when the while suite is empty (a pass statement),
|
In general, when the while suite is empty (a pass statement),
|
||||||
the do-while loop and break and continue statements should match
|
the do-while loop and break and continue statements should match
|
||||||
the semantics of do-while in other languages.
|
the semantics of do-while in other languages.
|
||||||
|
|
||||||
Likewise, when the do suite is empty, the do-while loop and
|
Likewise, when the do suite is empty, the do-while loop and
|
||||||
break and continue statements should match behavior found
|
break and continue statements should match behavior found
|
||||||
in regular while loops.
|
in regular while loops.
|
||||||
|
|
||||||
|
|
||||||
Future Statement
|
Future Statement
|
||||||
|
================
|
||||||
|
|
||||||
Because of the new keyword "do", the statement
|
Because of the new keyword "do", the statement::
|
||||||
|
|
||||||
from __future__ import do_while
|
from __future__ import do_while
|
||||||
|
|
||||||
will initially be required to use the do-while form.
|
will initially be required to use the do-while form.
|
||||||
|
|
||||||
|
|
||||||
Implementation
|
Implementation
|
||||||
|
==============
|
||||||
|
|
||||||
The first implementation of this PEP can compile the do-while loop
|
The first implementation of this PEP can compile the do-while loop
|
||||||
as an infinite loop with a test that exits the loop.
|
as an infinite loop with a test that exits the loop.
|
||||||
|
|
||||||
|
|
||||||
|
References
|
||||||
|
==========
|
||||||
|
|
||||||
|
.. [1] Guido van Rossum, PEP 315: do-while
|
||||||
|
https://mail.python.org/pipermail/python-ideas/2013-June/021610.html
|
||||||
|
|
||||||
|
.. [2] Raymond Hettinger, release plan for 2.5 ?
|
||||||
|
https://mail.python.org/pipermail/python-dev/2006-February/060718.html
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document is placed in the public domain.
|
This document is placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
sentence-end-double-space: t
|
indent-tabs-mode: nil
|
||||||
fill-column: 75
|
sentence-end-double-space: t
|
||||||
End:
|
fill-column: 75
|
||||||
|
End:
|
||||||
|
|
255
pep-3102.txt
255
pep-3102.txt
|
@ -5,186 +5,193 @@ Last-Modified: $Date$
|
||||||
Author: Talin <viridia@gmail.com>
|
Author: Talin <viridia@gmail.com>
|
||||||
Status: Final
|
Status: Final
|
||||||
Type: Standards Track
|
Type: Standards Track
|
||||||
Content-Type: text/plain
|
Content-Type: text/x-rst
|
||||||
Created: 22-Apr-2006
|
Created: 22-Apr-2006
|
||||||
Python-Version: 3.0
|
Python-Version: 3.0
|
||||||
Post-History: 28-Apr-2006, May-19-2006
|
Post-History: 28-Apr-2006, May-19-2006
|
||||||
|
|
||||||
|
|
||||||
Abstract
|
Abstract
|
||||||
|
========
|
||||||
|
|
||||||
This PEP proposes a change to the way that function arguments are
|
This PEP proposes a change to the way that function arguments are
|
||||||
assigned to named parameter slots. In particular, it enables the
|
assigned to named parameter slots. In particular, it enables the
|
||||||
declaration of "keyword-only" arguments: arguments that can only
|
declaration of "keyword-only" arguments: arguments that can only
|
||||||
be supplied by keyword and which will never be automatically
|
be supplied by keyword and which will never be automatically
|
||||||
filled in by a positional argument.
|
filled in by a positional argument.
|
||||||
|
|
||||||
|
|
||||||
Rationale
|
Rationale
|
||||||
|
=========
|
||||||
|
|
||||||
The current Python function-calling paradigm allows arguments to
|
The current Python function-calling paradigm allows arguments to
|
||||||
be specified either by position or by keyword. An argument can be
|
be specified either by position or by keyword. An argument can be
|
||||||
filled in either explicitly by name, or implicitly by position.
|
filled in either explicitly by name, or implicitly by position.
|
||||||
|
|
||||||
There are often cases where it is desirable for a function to take
|
There are often cases where it is desirable for a function to take
|
||||||
a variable number of arguments. The Python language supports this
|
a variable number of arguments. The Python language supports this
|
||||||
using the 'varargs' syntax ('*name'), which specifies that any
|
using the 'varargs' syntax (``*name``), which specifies that any
|
||||||
'left over' arguments be passed into the varargs parameter as a
|
'left over' arguments be passed into the varargs parameter as a
|
||||||
tuple.
|
tuple.
|
||||||
|
|
||||||
One limitation on this is that currently, all of the regular
|
One limitation on this is that currently, all of the regular
|
||||||
argument slots must be filled before the vararg slot can be.
|
argument slots must be filled before the vararg slot can be.
|
||||||
|
|
||||||
This is not always desirable. One can easily envision a function
|
This is not always desirable. One can easily envision a function
|
||||||
which takes a variable number of arguments, but also takes one
|
which takes a variable number of arguments, but also takes one
|
||||||
or more 'options' in the form of keyword arguments. Currently,
|
or more 'options' in the form of keyword arguments. Currently,
|
||||||
the only way to do this is to define both a varargs argument,
|
the only way to do this is to define both a varargs argument,
|
||||||
and a 'keywords' argument (**kwargs), and then manually extract
|
and a 'keywords' argument (``**kwargs``), and then manually extract
|
||||||
the desired keywords from the dictionary.
|
the desired keywords from the dictionary.
|
||||||
|
|
||||||
|
|
||||||
Specification
|
Specification
|
||||||
|
=============
|
||||||
|
|
||||||
Syntactically, the proposed changes are fairly simple. The first
|
Syntactically, the proposed changes are fairly simple. The first
|
||||||
change is to allow regular arguments to appear after a varargs
|
change is to allow regular arguments to appear after a varargs
|
||||||
argument:
|
argument::
|
||||||
|
|
||||||
def sortwords(*wordlist, case_sensitive=False):
|
def sortwords(*wordlist, case_sensitive=False):
|
||||||
...
|
...
|
||||||
|
|
||||||
This function accepts any number of positional arguments, and it
|
This function accepts any number of positional arguments, and it
|
||||||
also accepts a keyword option called 'case_sensitive'. This
|
also accepts a keyword option called 'case_sensitive'. This
|
||||||
option will never be filled in by a positional argument, but
|
option will never be filled in by a positional argument, but
|
||||||
must be explicitly specified by name.
|
must be explicitly specified by name.
|
||||||
|
|
||||||
Keyword-only arguments are not required to have a default value.
|
Keyword-only arguments are not required to have a default value.
|
||||||
Since Python requires that all arguments be bound to a value,
|
Since Python requires that all arguments be bound to a value,
|
||||||
and since the only way to bind a value to a keyword-only argument
|
and since the only way to bind a value to a keyword-only argument
|
||||||
is via keyword, such arguments are therefore 'required keyword'
|
is via keyword, such arguments are therefore 'required keyword'
|
||||||
arguments. Such arguments must be supplied by the caller, and
|
arguments. Such arguments must be supplied by the caller, and
|
||||||
they must be supplied via keyword.
|
they must be supplied via keyword.
|
||||||
|
|
||||||
The second syntactical change is to allow the argument name to
|
The second syntactical change is to allow the argument name to
|
||||||
be omitted for a varargs argument. The meaning of this is to
|
be omitted for a varargs argument. The meaning of this is to
|
||||||
allow for keyword-only arguments for functions that would not
|
allow for keyword-only arguments for functions that would not
|
||||||
otherwise take a varargs argument:
|
otherwise take a varargs argument::
|
||||||
|
|
||||||
def compare(a, b, *, key=None):
|
def compare(a, b, *, key=None):
|
||||||
...
|
...
|
||||||
|
|
||||||
The reasoning behind this change is as follows. Imagine for a
|
The reasoning behind this change is as follows. Imagine for a
|
||||||
moment a function which takes several positional arguments, as
|
moment a function which takes several positional arguments, as
|
||||||
well as a keyword argument:
|
well as a keyword argument::
|
||||||
|
|
||||||
def compare(a, b, key=None):
|
def compare(a, b, key=None):
|
||||||
...
|
...
|
||||||
|
|
||||||
Now, suppose you wanted to have 'key' be a keyword-only argument.
|
Now, suppose you wanted to have 'key' be a keyword-only argument.
|
||||||
Under the above syntax, you could accomplish this by adding a
|
Under the above syntax, you could accomplish this by adding a
|
||||||
varargs argument immediately before the keyword argument:
|
varargs argument immediately before the keyword argument::
|
||||||
|
|
||||||
def compare(a, b, *ignore, key=None):
|
def compare(a, b, *ignore, key=None):
|
||||||
...
|
...
|
||||||
|
|
||||||
Unfortunately, the 'ignore' argument will also suck up any
|
Unfortunately, the 'ignore' argument will also suck up any
|
||||||
erroneous positional arguments that may have been supplied by the
|
erroneous positional arguments that may have been supplied by the
|
||||||
caller. Given that we'd prefer any unwanted arguments to raise an
|
caller. Given that we'd prefer any unwanted arguments to raise an
|
||||||
error, we could do this:
|
error, we could do this::
|
||||||
|
|
||||||
def compare(a, b, *ignore, key=None):
|
def compare(a, b, *ignore, key=None):
|
||||||
if ignore: # If ignore is not empty
|
if ignore: # If ignore is not empty
|
||||||
raise TypeError
|
raise TypeError
|
||||||
|
|
||||||
|
As a convenient shortcut, we can simply omit the 'ignore' name,
|
||||||
|
meaning 'don't allow any positional arguments beyond this point'.
|
||||||
|
|
||||||
|
(Note: After much discussion of alternative syntax proposals, the
|
||||||
|
BDFL has pronounced in favor of this 'single star' syntax for
|
||||||
|
indicating the end of positional parameters.)
|
||||||
|
|
||||||
As a convenient shortcut, we can simply omit the 'ignore' name,
|
|
||||||
meaning 'don't allow any positional arguments beyond this point'.
|
|
||||||
|
|
||||||
(Note: After much discussion of alternative syntax proposals, the
|
|
||||||
BDFL has pronounced in favor of this 'single star' syntax for
|
|
||||||
indicating the end of positional parameters.)
|
|
||||||
|
|
||||||
|
|
||||||
Function Calling Behavior
|
Function Calling Behavior
|
||||||
|
=========================
|
||||||
|
|
||||||
The previous section describes the difference between the old
|
The previous section describes the difference between the old
|
||||||
behavior and the new. However, it is also useful to have a
|
behavior and the new. However, it is also useful to have a
|
||||||
description of the new behavior that stands by itself, without
|
description of the new behavior that stands by itself, without
|
||||||
reference to the previous model. So this next section will
|
reference to the previous model. So this next section will
|
||||||
attempt to provide such a description.
|
attempt to provide such a description.
|
||||||
|
|
||||||
When a function is called, the input arguments are assigned to
|
When a function is called, the input arguments are assigned to
|
||||||
formal parameters as follows:
|
formal parameters as follows:
|
||||||
|
|
||||||
- For each formal parameter, there is a slot which will be used
|
- For each formal parameter, there is a slot which will be used
|
||||||
to contain the value of the argument assigned to that
|
to contain the value of the argument assigned to that
|
||||||
parameter.
|
parameter.
|
||||||
|
|
||||||
- Slots which have had values assigned to them are marked as
|
- Slots which have had values assigned to them are marked as
|
||||||
'filled'. Slots which have no value assigned to them yet are
|
'filled'. Slots which have no value assigned to them yet are
|
||||||
considered 'empty'.
|
considered 'empty'.
|
||||||
|
|
||||||
- Initially, all slots are marked as empty.
|
- Initially, all slots are marked as empty.
|
||||||
|
|
||||||
- Positional arguments are assigned first, followed by keyword
|
- Positional arguments are assigned first, followed by keyword
|
||||||
arguments.
|
arguments.
|
||||||
|
|
||||||
- For each positional argument:
|
- For each positional argument:
|
||||||
|
|
||||||
o Attempt to bind the argument to the first unfilled
|
* Attempt to bind the argument to the first unfilled
|
||||||
parameter slot. If the slot is not a vararg slot, then
|
parameter slot. If the slot is not a vararg slot, then
|
||||||
mark the slot as 'filled'.
|
mark the slot as 'filled'.
|
||||||
|
|
||||||
o If the next unfilled slot is a vararg slot, and it does
|
* If the next unfilled slot is a vararg slot, and it does
|
||||||
not have a name, then it is an error.
|
not have a name, then it is an error.
|
||||||
|
|
||||||
o Otherwise, if the next unfilled slot is a vararg slot then
|
* Otherwise, if the next unfilled slot is a vararg slot then
|
||||||
all remaining non-keyword arguments are placed into the
|
all remaining non-keyword arguments are placed into the
|
||||||
vararg slot.
|
vararg slot.
|
||||||
|
|
||||||
- For each keyword argument:
|
- For each keyword argument:
|
||||||
|
|
||||||
o If there is a parameter with the same name as the keyword,
|
* If there is a parameter with the same name as the keyword,
|
||||||
then the argument value is assigned to that parameter slot.
|
then the argument value is assigned to that parameter slot.
|
||||||
However, if the parameter slot is already filled, then that
|
However, if the parameter slot is already filled, then that
|
||||||
is an error.
|
is an error.
|
||||||
|
|
||||||
o Otherwise, if there is a 'keyword dictionary' argument,
|
* Otherwise, if there is a 'keyword dictionary' argument,
|
||||||
the argument is added to the dictionary using the keyword
|
the argument is added to the dictionary using the keyword
|
||||||
name as the dictionary key, unless there is already an
|
name as the dictionary key, unless there is already an
|
||||||
entry with that key, in which case it is an error.
|
entry with that key, in which case it is an error.
|
||||||
|
|
||||||
o Otherwise, if there is no keyword dictionary, and no
|
* Otherwise, if there is no keyword dictionary, and no
|
||||||
matching named parameter, then it is an error.
|
matching named parameter, then it is an error.
|
||||||
|
|
||||||
- Finally:
|
- Finally:
|
||||||
|
|
||||||
o If the vararg slot is not yet filled, assign an empty tuple
|
* If the vararg slot is not yet filled, assign an empty tuple
|
||||||
as its value.
|
as its value.
|
||||||
|
|
||||||
o For each remaining empty slot: if there is a default value
|
* For each remaining empty slot: if there is a default value
|
||||||
for that slot, then fill the slot with the default value.
|
for that slot, then fill the slot with the default value.
|
||||||
If there is no default value, then it is an error.
|
If there is no default value, then it is an error.
|
||||||
|
|
||||||
In accordance with the current Python implementation, any errors
|
In accordance with the current Python implementation, any errors
|
||||||
encountered will be signaled by raising TypeError. (If you want
|
encountered will be signaled by raising ``TypeError``. (If you want
|
||||||
something different, that's a subject for a different PEP.)
|
something different, that's a subject for a different PEP.)
|
||||||
|
|
||||||
|
|
||||||
Backwards Compatibility
|
Backwards Compatibility
|
||||||
|
=======================
|
||||||
|
|
||||||
The function calling behavior specified in this PEP is a superset
|
The function calling behavior specified in this PEP is a superset
|
||||||
of the existing behavior - that is, it is expected that any
|
of the existing behavior - that is, it is expected that any
|
||||||
existing programs will continue to work.
|
existing programs will continue to work.
|
||||||
|
|
||||||
|
|
||||||
Copyright
|
Copyright
|
||||||
|
=========
|
||||||
|
|
||||||
This document has been placed in the public domain.
|
This document has been placed in the public domain.
|
||||||
|
|
||||||
|
|
||||||
Local Variables:
|
..
|
||||||
mode: indented-text
|
Local Variables:
|
||||||
indent-tabs-mode: nil
|
mode: indented-text
|
||||||
sentence-end-double-space: t
|
indent-tabs-mode: nil
|
||||||
fill-column: 70
|
sentence-end-double-space: t
|
||||||
coding: utf-8
|
fill-column: 70
|
||||||
End:
|
coding: utf-8
|
||||||
|
End:
|
||||||
|
|
Loading…
Reference in New Issue