pythonoverloadingmultiple-dispatch

Multiple dispatch - "function requires at least 1 positional argument"


In a multiple dispatch situation I don't understand why I constantly run into an error saying: TypeError: some_func requires at least 1 positional argument.

For example, we have a following function:

from functools import singledispatch

@singledispatch
def some_func(a, b):
    ...
    
@some_func.register
def _(a: str, b: int):
    print(f'{a=}, {b=}')
    
@some_func.register
def _(a: str, b: bool):
    print(f'{b=}, {a=}')

If I try to run:

some_func(a='a', b=10)

I get the error message:

    872 def wrapper(*args, **kw):
    873     if not args:
--> 874         raise TypeError(f'{funcname} requires at least '
    875                         '1 positional argument')
    877     return dispatch(args[0].__class__)(*args, **kw)

TypeError: some_func requires at least 1 positional argument

But it works fine if I make the first argument positional:

some_func('a', b=10)   # Out: a='a', b=10

Ok, then I'll try making them keyword-only...

@singledispatch
def some_func(*, a, b):
    ...
    
@some_func.register
def _(*, a: str, b: int):
    print(f'{a=}, {b=}')
    
@some_func.register
def _(*, a: str, b: bool):
    print(f'{b=}, {a=}')

Now if I try to run with keyword arguments I get the same result, but with this change if I try to make the first argument as positional I get a more expected error:

----> 1 some_func('a', b=10)

File C:\Python39\lib\functools.py:877, in singledispatch..wrapper(*args, **kw)
    873 if not args:
    874     raise TypeError(f'{funcname} requires at least '
    875                     '1 positional argument')
--> 877 return dispatch(args[0].__class__)(*args, **kw)

TypeError: _() takes 0 positional arguments but 1 positional argument (and 1 keyword-only argument) were given

So now the function simultaneously: requires a positional-only argument and takes no positional arguments.

I don't understand why this is happening? What is the reason for needing a positional-only arguments?


Solution

  • This seems to be an open python bug - the underlying wrapper expects at least one positional argument, otherwise an error is automatically raised (see definition of wrapper).