Is there any Python type-hinting syntax to state that a function takes the same parameters (and parameter types) as another function? In particular this is useful for wrapping, e.g.,
async def do_stuff(
param1: str,
param2: int,
param3: int = 14,
):
...
def run_async_thing(*args, **kwargs): # <--- What can I put here to say 'takes args like `do_stuff`'?
return asyncio.get_event_loop().run_until_complete(do_stuff(*args, **kwargs))
In this case, I would like to add type hinting to the run_async_thing
function to identify that it expects the same argument types as the do_stuff
function.
Is this possible, and if so, how?
The primary reason for wanting this is so that my tools (in particular PyCharm/IntellliJ IDEA) can figure out what arguments run_async_thing
should expect/accept. If it helps with documentation that's a bonus, but this is mainly for tooling.
The return value is annotated with the type float. Here the ‘->’ syntax for annotating the return value. Above we call func () twice, once with int arguments and once with string arguments. In both cases, func () does the right thing and annotations are simply ignored.
What are Annotations As we just went through in the introduction section, annotations are Python features that hint developers about the data types of the variables or function parameters and return type. They also increase the readability of your Python program.
Python Arbitrary Arguments Sometimes, we do not know in advance the number of arguments that will be passed into a function. Python allows us to handle this kind of situation through function calls with an arbitrary number of arguments. In the function definition, we use an asterisk (*) before the parameter name to denote this kind of argument.
Above we call func () twice, once with int arguments and once with string arguments. In both cases, func () does the right thing and annotations are simply ignored. So, we see the annotations have no effect on the execution of the function func ().
Define the parameters explicitly. You are unnecessarily generalizing the signature for run_async_thing
:
def run_async_thing(p1: str, p2: int, p3: int):
return asyncio.get_event_loop().run_until_complete(do_stuff(p1, p2, p3))
More generally, you can have run_async_thing
take a single tuple (or other object) as an argument. For example:
async def do_stuff(t: Tuple[str, int, int]):
...
def run_async_thing(args: Tuple[str, int, int]):
return asyncio.get_event_loop().run_until_complete(do_stuff(args))
The tuple type can be factored out:
StuffDoerArgs = Tuple[str, int, int]
async def do_stuff(t: StuffDoerArgs):
...
def run_async_thing(args: StuffDoerArgs):
...
You need to define the parameter types and return types. You can then copy the __annotations__
from one function to the other.
Example:
def abc(num: int, name: str) -> list:
return [num, name]
print(abc.__annotations__)
Output: {'num': <class 'int'>, 'name': <class 'str'>, 'return': <class 'list'>}
Now we create another function:
def xyz(num, name):
return [num, name]
print(xyz.__annotations__)
Output: {}
You can just copy over the __annotations__
output from one to the other.
xyz.__annotations__ = abc.__annotations__
So now:
print(xyz.__annotations__)
Output: {'num': <class 'int'>, 'name': <class 'str'>, 'return': <class 'list'>}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With