PEP 3102 for review and comment

Discussion in 'Python' started by Talin, May 20, 2006.

  1. Talin

    Talin Guest

    (Note: PEPs in the 3xxx number range are intended for Python 3000,
    however this particular PEP may be backported if there is support for
    it.)

    PEP: 3102
    Title: Keyword-Only Arguments
    Version: $Revision: 46053 $
    Last-Modified: $Date: 2006-05-19 22:23:44 -0700 (Fri, 19 May 2006) $
    Author: Talin <talin at acm.org>
    Status: Draft
    Type: Standards
    Content-Type: text/plain
    Created: 22-Apr-2006
    Python-Version: 3.0
    Post-History: 28-Apr-2006, May-19-2006


    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. The meaning of this is to
    allow for keyword-only arguments for functions that would not
    otherwise take 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'.

    (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

    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:
    Talin, May 20, 2006
    #1
    1. Advertising

  2. Talin

    Carl Banks Guest

    Talin wrote:
    > 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.


    Ick. Pretty big change hinging on subtle juxtaposition in the argument
    list. I don't like it, it doesn't stand out enough... but it makes
    logical sense and any other solution would have to be way more
    contrived. I think argument lists are already confusing enough with
    just mixing *, **, and default arguments.

    Two thoughts:

    Would these arguments go before of after **kwargs?

    This is apparently for Python 3.0. (I'd make the implementation
    schedule explicit, even if the PEP number implies it's Python 3.0.) It
    looks like Python 3.0 might declare function arguments like Ada. If
    so, what about a little modifier (like Ada's "in and out") instead?
    Problem with that is then positional arguments line up wrong. Ick.

    def func(a : int = 1): pass
    def func(a : kwonly int = 1): pass


    Carl Banks
    Carl Banks, May 20, 2006
    #2
    1. Advertising

  3. In article <>,
    "Talin" <> wrote:

    > (Note: PEPs in the 3xxx number range are intended for Python 3000,
    > however this particular PEP may be backported if there is support for
    > it.)
    >
    > PEP: 3102
    > Title: Keyword-Only Arguments

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


    The following is a 2nd syntactical change, and I strongly suggest
    listing it as such (since the first change can be made without this
    change):

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


    ....making this the third syntactical change:

    > The second syntactical change is to allow the argument name to
    > 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:
    >
    > def compare(a, b, *, key=None):


    Personally, my feelings are:

    +1 on allowing keyword arguments after *args. I have long wanted this
    and feel it is:
    - very useful (the alternative of abusing **kargs is ugly and doesn't
    support introspection)
    - an obvious and clear extension of current notation
    - removes an awkward limitation of current notation

    -1 on allowing keywords without values because:
    - if it is added, then it means something like the last change is
    required, and as I say next, I don't like it
    - why bother? it just makes work for the caller

    -1 on the use of * to mean a separator between positional args and
    keyword-only args because:
    - I think proposed syntax is confusing (there are more arguments in the
    argument list than the function accepts; yecch!!!) and hard to read
    - I don't think the added functionality is important enough to justify
    the awkward notation

    If folks are desperate enough for this last feature then please at least
    find a clearer notation. For example:
    def compare(a, b | key=None):
    but personally I'd rather skip it.

    Now if somebody could figure out a natural notation for boolean flags,
    *that'd* be useful (where the presence, absence or explicit negation of
    a keyword is all that is required to enable or disable a feature).

    -- Russell
    Russell E. Owen, May 22, 2006
    #3
  4. Talin

    Talin Guest

    Allowing keyword arguments without defaults may seem like a syntactical
    change, but in fact it's not. You can do this in Python now - any
    argument can be a 'keyword' argument, whether it has a default value or
    not. So for example:

    def func( a, b, c=0 ):
    pass

    func( a=1, b=2, c=3 )

    In other words, the use of '=' to indicate a keyword argument, and the
    use of '=' to indicate a default argument value have *nothing* to do
    with each other, other than the fact that they both have the
    requirement that they have to come after positional arguments.

    If you wanted to require keyword-only arguments to have default values,
    that would require adding an additional check, which would be a
    syntactical change.

    -- Talin
    Talin, May 22, 2006
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Alec S.
    Replies:
    10
    Views:
    10,093
    Alec S.
    Apr 16, 2005
  2. Guido van Rossum
    Replies:
    21
    Views:
    597
    Steven Bethard
    Jun 6, 2005
  3. molasses

    PEP 3102 for review and comment

    molasses, May 24, 2006, in forum: Python
    Replies:
    2
    Views:
    365
    Kay Schluehr
    May 24, 2006
  4. Tony Lownds
    Replies:
    4
    Views:
    452
    Tony Lownds
    Jan 1, 2007
  5. =?ISO-8859-1?Q?BJ=F6rn_Lindqvist?=

    Re: PEP 3107 Function Annotations for review and comment

    =?ISO-8859-1?Q?BJ=F6rn_Lindqvist?=, Dec 30, 2006, in forum: Python
    Replies:
    9
    Views:
    351
    Tony Lownds
    Jan 1, 2007
Loading...

Share This Page