PEP 3102 for review and comment
(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 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 argume
PEP 3102 for review and comment
I don't mind the naked star and will be happy if thats what we end up with. Though how about using *None? I think that makes the intention of the function clearer. eg. def compare(a, b, *None, key=None): Which to me reads as "no further positional arguments". Or alternatively: def compare(a, b, *0, key=None): -- Mark -- http://mail.python.org/mailman/listinfo/python-list
Re: PEP 3102 for review and comment
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: PEP 3102 for review and comment
In article <[EMAIL PROTECTED]>, "Talin" <[EMAIL PROTECTED]> 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 -- http://mail.python.org/mailman/listinfo/python-list
Re: PEP 3102 for review and comment
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 -- http://mail.python.org/mailman/listinfo/python-list
Re: PEP 3102 for review and comment
None is not currently a keyword -- http://mail.python.org/mailman/listinfo/python-list
Re: PEP 3102 for review and comment
molasses wrote: > I don't mind the naked star and will be happy if thats what we end up with. > > Though how about using *None? > I think that makes the intention of the function clearer. > > eg. > def compare(a, b, *None, key=None): > > Which to me reads as "no further positional arguments". > > Or alternatively: > def compare(a, b, *0, key=None): > > -- Mark Argh! Sorry, but this syntax seems to me a perlish hackaround. Although the star is clearly beautifull and vry pythonic ;) >From the PEP: 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. The current solution is fine and not very troublesome. But if you want to drop a named dict just replace it by an unnamed one ( unless you think this will seduce people to use devilish, horrible lambda ... ). Suggestions: def compare(a, b, *args, **kwd):# the classics def compare(a, b, *args, {"key":None}): # pass keywords in unnamed dict def compare(a, b, *args, {key=None}): # alternative syntax def compare(a, b, *args, **kwd={...,"key":None}): # having the cake and eating it Regards, Kay -- http://mail.python.org/mailman/listinfo/python-list