[Python-ideas] Positional only arguments

Ron Adam rrr at ronadam.com
Tue May 22 04:05:17 CEST 2007


Jim Jewett wrote:
>> What I would like is for unpack to be '^' instead of '*', then you would
>> have...
> 
> My first reaction was negative -- but then I remembered that I was
> caught by this trap myself more than once, because of the asymmetry
> between pack and unpack, with * magically doing the normally-right
> thing.
> 
> So now I wonder if I wouldn't like if after all, and I'm instead
> picking at the presentation, so you can make a stronger case.

Yes, it's gotten me a few times as well.  Usually when I have a class and 
some of the methods are accepting *args, **kwds, and some aren't.  Then I 
find I'm packing arguments in some cases and unpacking them in others in 
the same subclass, and the methods definitions are not on the same page so 
it isn't immediately obvious I got them mixed up.  As I said it isn't a 
computer issue, it's a human interface issue.


> On 5/21/07, Ron Adam <rrr at ronadam.com> wrote:
> 
>> Now if we use ^ for unpacking, and * for packing, it reduces the 
>> number of
>> meanings for the '*' and fixes the context of positional and keyword only
>> arguments.
> 
>> def f(a, ^(b=2, c=3), *rest):   b and c are positional only here.
> 
> I don't think there should ever be positional-only arguments *after* a
> keywordable argument.  Perhaps
> 
>    # a is a mandatory positional argument
>    # b is an optional positional argument
>    # c can be passed as a keyword, or as the third positional argument
>    def f(^a, ^b=2, c=3, *rest):
> 
> Or were you suggesting a tuple of the positional-only arguments, like
> 
>    # a is a mandatory positional argument
>    # b is an optional positional argument
>    # c can be passed as a keyword, or as the third positional argument
>    def f(^(a, b=2), c=3, *rest):

Ah, ok, I see what I missed.  I think I got optional args mixed up with 
positional args in my mind.  Not quite the same thing.

So yes, the second example fits what I was trying to think of better.

     # a is mandatory, positional
     # b is optional, positional
     # c is optional, positional, or by keyword
     # d is mandatory, keyword only
     # e is optional, keyword only
     def f(^(a, b=2), c=3, ^^(d, e=5)):


Of course it could be interpreted a bit differently given the unpacking 
context.

    # x is a two tuple (a, b)
    # y is a single value, c
    # z is a dict, {'d':4, 'e':5}
    result = f(x, y, z)

Which solves a different problem entirely.  ;-)

It allows you to specify unpacking behavior in the definition instead of 
requiring it on the calling side.


So I guess I'd have to fall back to the semi-colon as the positional only 
and keyword only designators.

    def f(a, b=2; c=3; d, e=5):


Or alternately use the colon as it is used in slices.

    def f(a, b=2: c=3: d, e=5):

I'd almost rather change the slices to semicolons and keep the colon unique 
and with only one purpose.

And ...

    def f(a, b=2, c=3)

would be equivalent to...

    def f(; a, b=2, c=3;):  No positional only, no keyword only


Anyway, I'm not sure there is a simple way to do this.  Sigh...


>> There is the possibility of extending this for use in other ways as well.
>>
>> xlist = [[1, 2], [3, 4, 5], [6, 7, 8, 9]]
>>
>> alist = [^x for x in xlist]
>>
>> This would have list "extend" behavior instead of list "append" behavior.
> 
> So alist == [1, 2, 3, 4, 5, 6, 7, 8, 9]?

Exactly.

Cheers,
    Ron





More information about the Python-ideas mailing list