Support for both variable number of args and keyword args? #87
-
Hi, thanks for this library -- it's great so far! I see there is support for keyword args via Is there a way to support both keyword and variable number of args at the same time? Consider this example: @multidispatch
def f(a,b): ...
@f.register
def f(a:int, b:int): return a+b
@f.register
def f(a:int, b:int, c:int): return a+b+c
f(1,2) # 3
f(1,2,3) # 6
f(1,2,c=3) # TypeError: got an unexpected keyword argument 'c'
f(a=1,b=2) # 3 Alternatively: @multidispatch
def f(a,b,c): ...
@f.register
def f(a:int, b:int): return a+b
@f.register
def f(a:int, b:int, c:int): return a+b+c
f(1,2) # 3
f(1,2,3) # 6
f(1,2,c=3) # 6
f(a=1,b=2) # TypeError: missing a required argument: 'c' |
Beta Was this translation helpful? Give feedback.
Replies: 5 comments
-
This seems to roughly give the behaviour I'm looking for, but I wonder if there's a better way to implement? MISSING = object()
@multidispatch
def f(a=MISSING, b=MISSING, c=MISSING):
supplied_args = {k:v for k,v in locals().items() if v is not MISSING}
try:
return f(**supplied_args)
except RecursionError:
raise DispatchError("Invalid args")
@f.register
def f(a:int, b:int): return a+b
@f.register
def f(a:int, b:int, c:int): return a+b+c
f(1,2) # 3
f(1,2,3) # 6
f(1,2,c=3) # 6
f(a=1,b=2) # 3
f('a') # DispatchError: Invalid args
f('a','b') # DispatchError: Invalid args
f('a','b','c','d') # TypeError: f() takes from 0 to 3 positional arguments but 4 were given |
Beta Was this translation helpful? Give feedback.
-
Yes, it has the limitation that it uses the first definition as the signature. The only general way to be that flexible would be check each function, which is what from multimethod import overload
@overload
def f(a,b): ...
@f.register
def f(a:int, b:int): return a+b
@f.register
def f(a:int, b:int, c:int): return a+b+c |
Beta Was this translation helpful? Give feedback.
-
Thanks, it seems like def literal(*s):
def inner(x):
return x in s
return inner
@overload
def f(a: Literal["example"]): return 1
@overload
def f(a: literal('other')): return 2
f('example') # TypeError: Cannot instantiate typing.Literal
f('other') # 2 |
Beta Was this translation helpful? Give feedback.
-
As of v1.10, |
Beta Was this translation helpful? Give feedback.
-
Implemented in a8e9fdd. |
Beta Was this translation helpful? Give feedback.
Yes, it has the limitation that it uses the first definition as the signature. The only general way to be that flexible would be check each function, which is what
overload
does. So if the performance difference isn't relevant for your case, that will work.