[Python-Dev] PEP 3102: Keyword-only arguments

Talin talin at acm.org
Sat Apr 29 20:27:49 CEST 2006


PEP: 3102
Title: Keyword-Only Arguments
Version: $Revision$
Last-Modified: $Date$
Author: Talin <talin at acm.org>
Status: Draft
Type: Standards
Content-Type: text/plain
Created: 22-Apr-2006
Python-Version: 3.0
Post-History:


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
     be omitted for a varargs argument:

         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'.


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:


More information about the Python-Dev mailing list