>>> from typing import overload
>>> @overload
... def hello(s: int):
... return "Got an integer!"
>>> def hello(s: str):
... return "Got a string"
Why does the calling hello(1)
call the function with the string argument? Ideally, the @overload
operator should handle it, right?
Unfortunately, python does not allow function overloading. Each time you think you are overloading function, you are just overwriting previous function declaration. Quote from the docs:
The @overload decorator allows describing functions and methods that support multiple different combinations of argument types. A series of @overload-decorated definitions must be followed by exactly one non-@overload-decorated definition (for the same function/method). The @overload-decorated definitions are for the benefit of the type checker only, since they will be overwritten by the non-@overload-decorated definition, while the latter is used at runtime but should be ignored by a type checker. At runtime, calling a @overload-decorated function directly will raise NotImplementedError.
The correct usage of typing.overload
is as follows:
from typing import overload
@overload
def hello(s: int) -> str:
...
@overload
def hello(s: str) -> str:
...
def hello(s):
if isinstance(s, int):
return "Got an integer!"
if isinstance(s, str):
return "Got a string"
raise ValueError('You must pass either int or str')
if __name__ == '__main__':
print(hello(1))
To show the actual benefit of typing.overload
lets change def hello(s: int)
to return int
instead of str
:
from typing import overload
@overload
def hello(s: int) -> int:
...
@overload
def hello(s: str) -> str:
...
def hello(s):
if isinstance(s, int):
return "Got an integer!"
if isinstance(s, str):
return "Got a string"
raise ValueError('You must pass either int or str')
if __name__ == '__main__':
print(hello(1))
a = hello(1) + 1
b = hello(1) + 'a'
Note, that the actual implementation still returns str
- python does not perform any checks here. However, PyCharm raises a warning:
mypy
also complains about invalid types:
➜ mypy test.py
test.py:25: error: Unsupported operand types for + ("int" and "str")
The purpose of typing
module is to allow third party tools to perform static checking of your code. There is no magic here - all types are ignored at runtime.