16

What's the best way to specify that the Callable variable fn takes *my_args as arguments? Like this:

def test(fn: Callable([Tuple[any]], None),
         *my_args: any) -> None:
    fn(*myargs)
Dewamuval
  • 327
  • 2
  • 10
  • 1
    Possible duplicate of [Type annotations for \*args and \*\*kwargs](https://stackoverflow.com/questions/37031928/type-annotations-for-args-and-kwargs) – b_c Nov 15 '19 at 19:28
  • Not really, at most it could be a duplicate of [this one](https://stackoverflow.com/questions/41725072/correct-usage-of-typing-types-for-args-and-kwargs), but it's unanswered – Dewamuval Nov 15 '19 at 19:29
  • Type hinting only provides information about how `fn` *can* be used, not how it *is* used. – chepner Nov 15 '19 at 20:49

2 Answers2

23

From the documentation on typing.Callable:

There is no syntax to indicate optional or keyword arguments; such function types are rarely used as callback types. Callable[..., ReturnType] (literal ellipsis) can be used to type hint a callable taking any number of arguments and returning ReturnType.

So in your case where *args is optional and ReturnType is None, use

fn: Callable[..., None]

P.s. I don't use type hints so please let me know if I've misunderstood anything.

wjandrea
  • 28,235
  • 9
  • 60
  • 81
11

Now with PEP 612 in Python 3.10, you can write this:

from typing import Callable, ParamSpec

P = ParamSpec("P")


def test(fn: Callable[P, None], *my_args: P.args, **my_kwargs: P.kwargs) -> None:
    fn(*myargs, **my_kwargs)

Then any calls to test will be properly type checked.

CCCC_David
  • 361
  • 3
  • 4