python - with `*args`, keyword arguments become positional? -


example, define function

def myfunc(a=1, *args):     print(a)     # *args have other functionality, example passed class instance, or whatever 

problem is: when calling myfunc, can't pass expected positional arguments *args first, pass keyword argument a. example, if expected *args contain number, can't

myfunc(3, a=4) 

this raise error, stating multiple assignments received a. can't myfunc(a=4, b=5, 3) obviously. can

myfunc(4, 3) 

so seems, *args, keyword argument a becomes positional?

the example here function, applies classes. subclass __init__(a=3, *args) wants keyword argument a , other 99 required arguments pass super. wouldn't want repeat 99 arguments definition in subclass, rather *args , pass super. keyword argument a becomes positional.

this class , subclass example real problem in coding. want subclass optional, keyword argument a, , 99 required arguments super. don't see good, clean way around problem.

i can't first bump this, couldn't find answer.

a isn't positional-only:

>>> import inspect >>> def myfunc(a=1, *args): ...     print(a) >>> inspect.signature(myfunc).parameters['a'].kind <_parameterkind.positional_or_keyword: 1> 

and indeed can passed in keyword-argument:

>>> myfunc(a=4) 4 

however, noted, want provide subsequent positional arguments, have provide positional parameter. has nothing *args, that's how positional arguments work:

>>> def myfunc2(a, b): ...     print(a) >>> myfunc2(1, a=2) typeerror: myfunc2() got multiple values argument 'a' 

it either has first of positional arguments or arguments have passed name.

however *args complicates situation somewhat, because collects positional arguments. means if should collect anything have pass in previous parameters position.

but in case want roll own special case accept *args, **kwargs , first check if it's passed keyword (named) argument or, if not, first positional argument:

>>> def myfunc3(*args, **kwargs): ...     if 'a' in kwargs: ...         = kwargs.pop('a') ...     else: ...         = args[0] ...         args = args[1:] ...     print(a, args, kwargs) >>> myfunc3(1, a=2) 2 (1,) {} >>> myfunc3(2, 1) 2 (1,) {} 

that should give results expected need explicit in documentation how argument should passed in because breaks semantics of pythons signature model.


Comments