Overload decorator in typings module doesn't seem to behave as expected

若如初见. 提交于 2020-05-15 11:40:09

问题


>>> 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?


回答1:


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.



来源:https://stackoverflow.com/questions/52034771/overload-decorator-in-typings-module-doesnt-seem-to-behave-as-expected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!