[Python-3000] PEP 3102
Joel Bender
jjb5 at cornell.edu
Fri Feb 15 17:46:28 CET 2008
Dj Gilcrease wrote:
> On Thu, Feb 14, 2008 at 6:04 PM, Greg Ewing <greg.ewing at canterbury.ac.nz> wrote:
>> Guido van Rossum wrote:
>> > Now can you come up with a syntax for positional-only
>> > arguments? So far everybody has failed at that, and there are some use
>> > cases where it's useful too.
>
>
> throwing some ideas around...
How about a BNFish notation? Use brackets around optional parameters.
def test([arg1, [arg2,]] arg3):
...
I haven't found an example of what the value of an unspecified
positional only argument would be, I think it should be required:
def test([arg1=1,] arg2): return (arg1, arg2)
This could also accommodate trailing positional only args, even though
the existing syntax already has it (but keep reading):
def test(arg1 [, arg2=2]): return (arg1, arg2)
assert test(1) == (1, 2)
assert test(1,3) == (1, 3)
If both were provided:
def test([arg1=1,] arg2 [, arg3=3]): ... # error
I would expect it to be an "ambiguous combination of optional
positional-only arguments" syntax error (as opposed to runtime error).
If you wanted arg2 specified when arg1 is:
def test([arg1=1, arg2=2,] arg3): return (arg1, arg2, arg3)
assert test(9) == (1, 2, 9)
assert test(7, 8, 9) == (7, 8, 9)
test(8, 9) # error
With nesting you can specify which one is more optional:
def test([[arg1=1,] arg2=2,] arg3): return (arg1, arg2, arg3)
assert test(9) == (1, 2, 9)
assert test(8, 9) == (1, 8, 9)
def test([arg1=1, [arg2=2,]] arg3): return (arg1, arg2, arg3)
assert test(8, 9) == (8, 2, 9)
Capturing all of the args except the last one:
def test([*arg1,] arg2): return (arg1, arg2)
assert test(9) == ((), 9)
assert test(8, 9) == ((8,), 9)
assert test(7, 8, 9) == ((7, 8), 9)
First is a little more important:
def test([arg1=1, *arg2,] arg3): return (arg1, arg2, arg3)
assert test(9) == (1, (), 9)
assert test(8, 9) == (8, (), 9)
assert test(7, 8, 9) == (7, (8,), 9)
Force the end of positional arguments to switch to keywords:
def test([*arg1,] arg2, *, arg3=3): return (arg1, arg2, arg3)
Specifying more than one dumping spot for additional positional
parameters is ambiguous:
def test([arg1=1, *arg2,] arg3, *arg4): ... # error
Specifying default values for a positional argument may make it ambiguous:
def test([arg1=1,] arg2, arg3=3): return (arg1, arg2, arg3)
This is OK, but not recommended, it's more complicated than it needs to be:
def test(arg1 [, arg2=1 [, arg3=2]]): return (arg1, arg2, arg3)
And now for something completely different:
def test(arg1 [[, arg2=2], arg3=3]): return (arg1, arg2, arg3)
assert test(8) == (8, 2, 3)
assert test(8, 9) == (8, 2, 9)
assert test(7, 8, 9) == (7, 8, 9)
Like the other dumping spot:
def test(arg1 [[, *arg2], arg3=3]): return (arg1, arg2, arg3)
assert test(8) == (8, (), 3)
assert test(8, 9) == (8, (), 9)
assert test(7, 8, 9) == (7, (8,), 9)
Nested galore:
def test([arg1=1, [[*arg2,] arg3=3,]] arg4):
return (arg1, arg2, arg3, arg4)
assert test(7) = (1, (), 3, 7)
assert test(7, 8) = (7, (), 3, 8)
assert test(7, 8, 9) = (7, (), 8, 9)
assert test(7, 8, 9, 10) = (7, (8,), 9, 10)
The notation for an optional tuple that gets ripped apart seems busy,
but is still grokable:
def test([(arg1, arg2)=(1, 2),] arg3): return (arg1, arg2, arg3)
assert test(8) == (1, 2, 8)
assert test((7, 8), 9) == (7, 8, 9)
Joel
More information about the Python-3000
mailing list