[Python-checkins] peps: Added PEP 457, Syntax For Positional-Only Parameters.
larry.hastings
python-checkins at python.org
Wed Oct 9 01:24:09 CEST 2013
http://hg.python.org/peps/rev/52b7feaa098b
changeset: 5182:52b7feaa098b
user: Larry Hastings <larry at hastings.org>
date: Wed Oct 09 01:23:55 2013 +0200
summary:
Added PEP 457, Syntax For Positional-Only Parameters.
files:
pep-0457.txt | 334 +++++++++++++++++++++++++++++++++++++++
1 files changed, 334 insertions(+), 0 deletions(-)
diff --git a/pep-0457.txt b/pep-0457.txt
new file mode 100644
--- /dev/null
+++ b/pep-0457.txt
@@ -0,0 +1,334 @@
+PEP: 457
+Title: Syntax For Positional-Only Parameters
+Version: $Revision$
+Last-Modified: $Date$
+Author: Larry Hastings <larry at hastings.org>
+Discussions-To: Python-Dev <python-dev at python.org>
+Status: Draft
+Type: Informational
+Content-Type: text/x-rst
+Created: 08-Oct-2013
+
+
+========
+Overview
+========
+
+This PEP proposes a syntax for positional-only parameters in Python.
+Positional-only parameters are parameters without an externally-usable
+name; when a function accepting positional-only parameters is called,
+positional arguments are mapped to these parameters based solely on
+their position.
+
+=========
+Rationale
+=========
+
+Python has always supported positional-only parameters.
+Early versions of Python lacked the concept of specifying
+parameters by name, so naturally all parameters were
+positional-only. This changed around Python 1.0, when
+all parameters suddenly became positional-or-keyword.
+But, even in current versions of Python, many CPython
+"builtin" functions still only accept positional-only
+arguments.
+
+Functions implemented in modern Python can accept
+an arbitrary number of positional-only arguments, via the
+variadic ``*args`` parameter. However, there is no Python
+syntax to specify accepting a specific number of
+positional-only parameters. Put another way, there are
+many builtin functions whose signatures are simply not
+expressable with Python syntax.
+
+This PEP proposes a backwards-compatible syntax that should
+permit implementing any builtin in pure Python code.
+
+-----------------------------------------------------
+Positional-Only Parameter Semantics In Current Python
+-----------------------------------------------------
+
+There are many, many examples of builtins that only
+accept positional-only parameters. The resulting
+semantics are easily experienced by the Python
+programmer--just try calling one, specifying its
+arguments by name::
+
+ >>> pow(x=5, y=3)
+ Traceback (most recent call last):
+ File "<stdin>", line 1, in <module>
+ TypeError: pow() takes no keyword arguments
+
+In addition, there are some functions with particularly
+interesting semantics:
+
+ * ``range()``, which accepts an optional parameter
+ to the *left* of its required parameter. [#RANGE]_
+
+ * ``dict()``, whose mapping/iterator parameter is optional and
+ semantically must be positional-only. Any externally
+ visible name for this parameter would occlude
+ that name going into the ``**kwarg`` keyword variadic
+ parameter dict! [#DICT]_
+
+Obviously one can simulate any of these in pure Python code
+by accepting ``(*args, **kwargs)`` and parsing the arguments
+by hand. But this results in a disconnect between the
+Python function's signature and what it actually accepts,
+not to mention the work of implementing said argument parsing.
+
+==========
+Motivation
+==========
+
+This PEP does not propose we implement positional-only
+parameters in Python. The goal of this PEP is simply
+to define the syntax, so that:
+
+ * Documentation can clearly, unambiguously, and
+ consistently express exactly how the arguments
+ for a function will be interpreted.
+
+ * The syntax is reserved for future use, in case
+ the community decides someday to add positional-only
+ parameters to the language.
+
+ * Argument Clinic can use a variant of the syntax
+ as part of its input when defining
+ the arguments for built-in functions.
+
+=================================================================
+The Current State Of Documentation For Positional-Only Parameters
+=================================================================
+
+The documentation for positional-only parameters is incomplete
+and inconsistent:
+
+* Some functions denote optional groups of positional-only arguments
+ by enclosing them in nested square brackets. [#BORDER]_
+
+* Some functions denote optional groups of positional-only arguments
+ by presenting multiple prototypes with varying numbers of
+ arguments. [#SENDFILE]_
+
+* Some functions use *both* of the above approaches. [#RANGE]_ [#ADDCH]_
+
+One more important idea to consider: currently in the documentation
+there's no way to tell whether a function takes positional-only
+parameters. ``open()`` accepts keyword arguments, ``ord()`` does
+not, but there is no way of telling just by reading the
+documentation that this is true.
+
+====================
+Syntax And Semantics
+====================
+
+From the "ten-thousand foot view", and ignoring ``*args`` and ``**kwargs``
+for now, the grammar for a function definition currently looks like this::
+
+ def name(positional_or_keyword_parameters, *, keyword_only_parameters):
+
+Building on that perspective, the new syntax for functions would look
+like this::
+
+ def name(positional_only_parameters, /, positional_or_keyword_parameters,
+ *, keyword_only_parameters):
+
+All parameters before the ``/`` are positional-only. If ``/`` is
+not specified in a function signature, that function does not
+accept any positional-only parameters.
+
+Positional-only parameters can be optional, but the mechanism is
+significantly different from positional-or-keyword or keyword-only
+parameters. Positional-only parameters don't accept default
+values. Instead, positional-only parameters can be specified
+in optional "groups". Groups of parameters are surrounded by
+square brackets, like so::
+
+ def addch([y, x,] ch, [attr], /):
+
+Positional-only parameters that are not in an option group are
+"required" positional-only parameters. All "required" positional-only
+parameters must be contiguous.
+
+Parameters in an optional group accept arguments in a group; you
+must provide arguments either for all of the them or for none of them.
+Using the example of ``addch()`` above, you could not call ``addch()``
+in such a way that ``x`` was specified but ``y`` was not (and vice versa).
+The mapping of positional parameters to optional groups is done
+based on fitting the number of parameters to groups. Based on the
+above definition, ``addch()`` would assign arguments to parameters
+in the following way:
+
+ +-------------------+------------------------------+
+ |Number of arguments|Parameter assignment |
+ +-------------------+------------------------------+
+ |0 |*raises an exception* |
+ +-------------------+------------------------------+
+ |1 |``ch`` |
+ +-------------------+------------------------------+
+ |2 |``ch``, ``attr`` |
+ +-------------------+------------------------------+
+ |3 |``y``, ``x``, ``ch`` |
+ +-------------------+------------------------------+
+ |4 |``y``, ``x``, ``ch``, ``attr``|
+ +-------------------+------------------------------+
+ |5 or more |*raises an exception* |
+ +-------------------+------------------------------+
+
+
+More semantics of positional-only parameters:
+
+ * Although positional-only parameter technically have names,
+ these names are internal-only; positional-only parameters
+ are *never* externally addressable by name. (Similarly
+ to ``*args`` and ``**kwargs``.)
+
+ * It's possible to nest option groups.
+
+ * If there are no required parameters, all option groups behave
+ as if they're to the right of the required parameter group.
+
+ * For clarity and consistency, the comma for a parameter always
+ comes immediately after the parameter name. It's a syntax error
+ to specify a square bracket between the name of a parameter and
+ the following comma. (This is far more readable than putting
+ the comma outside the square bracket, particularly for nested
+ groups.)
+
+ * If there are arguments after the ``/``, then you must specify
+ a comma after the ``/``, just as there is a comma
+ after the ``*`` denoting the shift to keyword-only parameters.
+
+ * This syntax has no effect on ``*args`` or ``**kwargs``.
+
+It's possible to specify a function prototype where the mapping
+of arguments to parameters is ambiguous. Consider::
+
+ def range([start,] stop, [range], /):
+
+Python disambiguates these situations by preferring optional groups
+to the *left* of the required group.
+
+======================
+Additional Limitations
+======================
+
+Argument Clinic uses a form of this syntax for specifying
+builtins. It imposes further limitations that are
+theoretically unnecessary but make the implementation
+easier. Specifically:
+
+* A function that has positional-only parameters currently
+ cannot have any other kind of parameter. (This will
+ probably be relaxed slightly in the near future.)
+
+* Multiple option groups on either side of the required
+ positional-only parameters must be nested, with the
+ nesting getting deeper the further away the group is
+ from the required positional-parameter group.
+
+ Put another way:
+ all the left-brackets for option groups to the
+ left of the required group must be specified contiguously,
+ and
+ all the right-brackets for option groups to the
+ right of the required group must be specified contiguously.
+
+
+==============================
+Notes For A Future Implementor
+==============================
+
+If we decide to implement positional-only parameters in a future
+version of Python, we'd have to do some additional work to preserve
+their semantics. The problem: how do we inform a parameter that
+no value was passed in for it when the function was called?
+
+The obvious solution: add a new singleton constant to Python
+that is passed in when a parameter is not mapped to an argument.
+I propose that the value be called called ``undefined``,
+and be a singleton of a special class called ``Undefined``.
+If a positional-only parameter did not receive an argument
+when called, its value would be set to ``undefined``.
+
+But this raises a further problem. How do can we tell the
+difference between "this positional-only parameter did not
+receive an argument" and "the caller passed in ``undefined``
+for this parameter"?
+
+It'd be nice to make it illegal to pass ``undefined`` in
+as an argument to a function--to, say, raise an exception.
+But that would slow Python down, and the "consenting adults"
+rule appears applicable here. So making it illegal should
+probably be strongly discouraged but not outright prevented.
+
+However, it should be allowed (and encouraged) for user
+functions to specify ``undefined`` as a default value for
+parameters.
+
+====================
+Unresolved Questions
+====================
+
+There are three types of parameters in Python:
+
+ 1. positional-only parameters,
+ 2. positional-or-keyword parameters, and
+ 3. keyword-only parameters.
+
+Python allows functions to have both 2 and 3. And some
+builtins (e.g. range) have both 1 and 3. Does it make
+sense to have functions that have both 1 and 2? Or
+all of the above?
+
+
+======
+Thanks
+======
+
+Credit for the use of '/' as the separator between positional-only and positional-or-keyword
+parameters goes to Guido van Rossum, in a proposal from 2012. [#GUIDO]_
+
+Credit for making left option groups higher precedence goes to
+Nick Coghlan. (Conversation in person at PyCon US 2013.)
+
+.. [#DICT]
+ http://docs.python.org/3/library/stdtypes.html#dict
+
+.. [#RANGE]
+ http://docs.python.org/3/library/functions.html#func-range
+
+.. [#BORDER]
+ http://docs.python.org/3/library/curses.html#curses.window.border
+
+.. [#SENDFILE]
+ http://docs.python.org/3/library/os.html#os.sendfile
+
+.. [#ADDCH]
+ http://docs.python.org/3/library/curses.html#curses.window.addch
+
+.. [#GUIDO]
+ Guido van Rossum, posting to python-ideas, March 2012:
+ http://mail.python.org/pipermail/python-ideas/2012-March/014364.html
+ and
+ http://mail.python.org/pipermail/python-ideas/2012-March/014378.html
+ and
+ http://mail.python.org/pipermail/python-ideas/2012-March/014417.html
+
+=========
+Copyright
+=========
+
+This document has been placed in the public domain.
+
+
+
+..
+ Local Variables:
+ mode: indented-text
+ indent-tabs-mode: nil
+ sentence-end-double-space: t
+ fill-column: 70
+ coding: utf-8
+ End:
--
Repository URL: http://hg.python.org/peps
More information about the Python-checkins
mailing list