2006-04-26 16:33:25 -04:00
|
|
|
|
PEP: 3102
|
|
|
|
|
Title: Keyword-Only Arguments
|
|
|
|
|
Version: $Revision$
|
|
|
|
|
Last-Modified: $Date$
|
2015-12-27 12:09:06 -05:00
|
|
|
|
Author: Talin <viridia@gmail.com>
|
2009-01-19 11:08:45 -05:00
|
|
|
|
Status: Final
|
2007-04-14 22:10:27 -04:00
|
|
|
|
Type: Standards Track
|
2006-04-26 16:33:25 -04:00
|
|
|
|
Content-Type: text/plain
|
|
|
|
|
Created: 22-Apr-2006
|
|
|
|
|
Python-Version: 3.0
|
2006-05-20 01:23:44 -04:00
|
|
|
|
Post-History: 28-Apr-2006, May-19-2006
|
2006-04-26 16:33:25 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Abstract
|
|
|
|
|
|
|
|
|
|
This PEP proposes a change to the way that function arguments are
|
|
|
|
|
assigned to named parameter slots. In particular, it enables the
|
|
|
|
|
declaration of "keyword-only" arguments: arguments that can only
|
|
|
|
|
be supplied by keyword and which will never be automatically
|
|
|
|
|
filled in by a positional argument.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Rationale
|
|
|
|
|
|
|
|
|
|
The current Python function-calling paradigm allows arguments to
|
|
|
|
|
be specified either by position or by keyword. An argument can be
|
|
|
|
|
filled in either explicitly by name, or implicitly by position.
|
|
|
|
|
|
|
|
|
|
There are often cases where it is desirable for a function to take
|
|
|
|
|
a variable number of arguments. The Python language supports this
|
|
|
|
|
using the 'varargs' syntax ('*name'), which specifies that any
|
|
|
|
|
'left over' arguments be passed into the varargs parameter as a
|
|
|
|
|
tuple.
|
|
|
|
|
|
|
|
|
|
One limitation on this is that currently, all of the regular
|
|
|
|
|
argument slots must be filled before the vararg slot can be.
|
|
|
|
|
|
|
|
|
|
This is not always desirable. One can easily envision a function
|
|
|
|
|
which takes a variable number of arguments, but also takes one
|
|
|
|
|
or more 'options' in the form of keyword arguments. Currently,
|
|
|
|
|
the only way to do this is to define both a varargs argument,
|
|
|
|
|
and a 'keywords' argument (**kwargs), and then manually extract
|
|
|
|
|
the desired keywords from the dictionary.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Specification
|
|
|
|
|
|
|
|
|
|
Syntactically, the proposed changes are fairly simple. The first
|
|
|
|
|
change is to allow regular arguments to appear after a varargs
|
|
|
|
|
argument:
|
|
|
|
|
|
|
|
|
|
def sortwords(*wordlist, case_sensitive=False):
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
This function accepts any number of positional arguments, and it
|
|
|
|
|
also accepts a keyword option called 'case_sensitive'. This
|
|
|
|
|
option will never be filled in by a positional argument, but
|
|
|
|
|
must be explicitly specified by name.
|
|
|
|
|
|
|
|
|
|
Keyword-only arguments are not required to have a default 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
|
|
|
|
|
is via keyword, such arguments are therefore 'required keyword'
|
|
|
|
|
arguments. Such arguments must be supplied by the caller, and
|
|
|
|
|
they must be supplied via keyword.
|
|
|
|
|
|
|
|
|
|
The second syntactical change is to allow the argument name to
|
2006-05-20 01:23:44 -04:00
|
|
|
|
be omitted for a varargs argument. The meaning of this is to
|
|
|
|
|
allow for keyword-only arguments for functions that would not
|
|
|
|
|
otherwise take a varargs argument:
|
2006-04-26 16:33:25 -04:00
|
|
|
|
|
|
|
|
|
def compare(a, b, *, key=None):
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
The reasoning behind this change is as follows. Imagine for a
|
|
|
|
|
moment a function which takes several positional arguments, as
|
|
|
|
|
well as a keyword argument:
|
|
|
|
|
|
|
|
|
|
def compare(a, b, key=None):
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
Now, suppose you wanted to have 'key' be a keyword-only argument.
|
|
|
|
|
Under the above syntax, you could accomplish this by adding a
|
|
|
|
|
varargs argument immediately before the keyword argument:
|
|
|
|
|
|
|
|
|
|
def compare(a, b, *ignore, key=None):
|
|
|
|
|
...
|
|
|
|
|
|
|
|
|
|
Unfortunately, the 'ignore' argument will also suck up any
|
|
|
|
|
erroneous positional arguments that may have been supplied by the
|
|
|
|
|
caller. Given that we'd prefer any unwanted arguments to raise an
|
|
|
|
|
error, we could do this:
|
|
|
|
|
|
|
|
|
|
def compare(a, b, *ignore, key=None):
|
|
|
|
|
if ignore: # If ignore is not empty
|
|
|
|
|
raise TypeError
|
|
|
|
|
|
|
|
|
|
As a convenient shortcut, we can simply omit the 'ignore' name,
|
|
|
|
|
meaning 'don't allow any positional arguments beyond this point'.
|
2006-05-20 01:23:44 -04:00
|
|
|
|
|
|
|
|
|
(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.)
|
|
|
|
|
|
2006-04-26 16:33:25 -04:00
|
|
|
|
|
|
|
|
|
Function Calling Behavior
|
|
|
|
|
|
|
|
|
|
The previous section describes the difference between the old
|
|
|
|
|
behavior and the new. However, it is also useful to have a
|
|
|
|
|
description of the new behavior that stands by itself, without
|
|
|
|
|
reference to the previous model. So this next section will
|
|
|
|
|
attempt to provide such a description.
|
|
|
|
|
|
|
|
|
|
When a function is called, the input arguments are assigned to
|
|
|
|
|
formal parameters as follows:
|
|
|
|
|
|
|
|
|
|
- For each formal parameter, there is a slot which will be used
|
|
|
|
|
to contain the value of the argument assigned to that
|
|
|
|
|
parameter.
|
|
|
|
|
|
|
|
|
|
- Slots which have had values assigned to them are marked as
|
|
|
|
|
'filled'. Slots which have no value assigned to them yet are
|
|
|
|
|
considered 'empty'.
|
|
|
|
|
|
|
|
|
|
- Initially, all slots are marked as empty.
|
|
|
|
|
|
|
|
|
|
- Positional arguments are assigned first, followed by keyword
|
|
|
|
|
arguments.
|
|
|
|
|
|
|
|
|
|
- For each positional argument:
|
|
|
|
|
|
|
|
|
|
o Attempt to bind the argument to the first unfilled
|
|
|
|
|
parameter slot. If the slot is not a vararg slot, then
|
|
|
|
|
mark the slot as 'filled'.
|
|
|
|
|
|
|
|
|
|
o If the next unfilled slot is a vararg slot, and it does
|
|
|
|
|
not have a name, then it is an error.
|
|
|
|
|
|
|
|
|
|
o Otherwise, if the next unfilled slot is a vararg slot then
|
|
|
|
|
all remaining non-keyword arguments are placed into the
|
|
|
|
|
vararg slot.
|
|
|
|
|
|
|
|
|
|
- For each keyword argument:
|
|
|
|
|
|
|
|
|
|
o If there is a parameter with the same name as the keyword,
|
|
|
|
|
then the argument value is assigned to that parameter slot.
|
|
|
|
|
However, if the parameter slot is already filled, then that
|
|
|
|
|
is an error.
|
|
|
|
|
|
|
|
|
|
o Otherwise, if there is a 'keyword dictionary' argument,
|
|
|
|
|
the argument is added to the dictionary using the keyword
|
|
|
|
|
name as the dictionary key, unless there is already an
|
|
|
|
|
entry with that key, in which case it is an error.
|
|
|
|
|
|
|
|
|
|
o Otherwise, if there is no keyword dictionary, and no
|
|
|
|
|
matching named parameter, then it is an error.
|
|
|
|
|
|
|
|
|
|
- Finally:
|
|
|
|
|
|
|
|
|
|
o If the vararg slot is not yet filled, assign an empty tuple
|
|
|
|
|
as its value.
|
|
|
|
|
|
|
|
|
|
o For each remaining empty slot: if there is a default value
|
|
|
|
|
for that slot, then fill the slot with the default value.
|
|
|
|
|
If there is no default value, then it is an error.
|
|
|
|
|
|
|
|
|
|
In accordance with the current Python implementation, any errors
|
|
|
|
|
encountered will be signaled by raising TypeError. (If you want
|
|
|
|
|
something different, that's a subject for a different PEP.)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Backwards Compatibility
|
|
|
|
|
|
|
|
|
|
The function calling behavior specified in this PEP is a superset
|
|
|
|
|
of the existing behavior - that is, it is expected that any
|
|
|
|
|
existing programs will continue to work.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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:
|