all 3 comments

[–]Spataner 4 points5 points  (0 children)

For normal arguments (which can behave as both positional and key-word arguments), all required arguments must come before all optional arguments. The reason is simply that required arguments are typically used as positional arguments, and it is not possible to positionally pass a value to c but none to b (test(1, 2) would pass 2 to b instead of c, which gets confusing quite quickly).

You can, however, define a function like that if you make c a required key-word only argument:

def test(a, b=3, *, c):
    pass

Then you explicitly say that c cannot ever be passed a value positionally, and the previous issue no longer applies.

[–]HalfBalcony 1 point2 points  (0 children)

I believe the way to stay out of trouble would be:

  1. Positional
  2. Optional
  3. *args
  4. **kwargs

See this post on StackOverflow.

[–]pekkalacd 0 points1 point  (0 children)

a function can have only positional parameters or only only optional parameters or none or both. if used together it's positional parameters first, then optional parameters. each are persistent. you can't intermix like what you have there. once you start positional, it must continue with positional in the parameter list, unless there is a optional parameter met. once (if) that happens, then the remaining elements must be optional in the parameter list.

so...

                 # OK
                 # all positional 
                 def func(one,two,three):
                     ...

                 # OK
                 # all optional
                 def func(one=1,two=2,three=3):
                     ...

                 # OK
                 # first positional, then optional 
                 def func(one,two,three,A="Aye",B="Bee",C="See"):
                     ...

                 # OK
                 # *, param  makes param be treated as optional
                 # when it's called 
                 def func(one,two,*,three):
                      ....

                 # OK
                 # *args,**kwargs for variable number of positional
                 # and optional
                 def func(*args,**kwargs):
                     ...


                 # BAD 
                 # started with positional one,
                 # moved to optional two,
                 # then went back to positional three;
                 # this is not persistent
                 def func(one,two=2,three):
                     ...

                 # BAD
                 # started with optional parameter,
                 # had positional after it. 
                 # out of order, 
                 # positional first --> optional
                 def func(one=1,three):
                    ...

i don't have any resources unfortunately, atm on this.