python - 类型模块中的重载装饰器似乎没有按预期运行
问题描述
>>> from typing import overload
>>> @overload
... def hello(s: int):
... return "Got an integer!"
>>> def hello(s: str):
... return "Got a string"
为什么调用hello(1)
调用带有字符串参数的函数?理想情况下,@overload
操作员应该处理它,对吗?
解决方案
不幸的是,python 不允许函数重载。每次你认为你正在重载函数时,你只是在覆盖之前的函数声明。从文档中引用:
@overload 装饰器允许描述支持多种不同参数类型组合的函数和方法。一系列@overload-decorated 定义必须紧跟一个非@overload-decorated 定义(对于相同的函数/方法)。@overload-decorated 定义仅用于类型检查器,因为它们将被非@overload-decorated 定义覆盖,而后者在运行时使用但应被类型检查器忽略。在运行时,直接调用 @overload-decorated 函数将引发 NotImplementedError。
的正确用法typing.overload
如下:
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))
为了显示typing.overload
让我们更改def hello(s: int)
为 returnint
而不是的实际好处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'
请注意,实际实现仍然返回str
- python 在这里不执行任何检查。然而,PyCharm 提出了一个警告:
mypy
还抱怨无效类型:
➜ mypy test.py
test.py:25: error: Unsupported operand types for + ("int" and "str")
模块的目的typing
是允许第三方工具对您的代码执行静态检查。这里没有魔法——所有类型在运行时都会被忽略。
推荐阅读
- java - 滚动时 AppBar 未完全隐藏在状态栏中
- reactjs - 反应路由器链接以有条件地渲染按钮
- javascript - JavaScript 编译器
- amazon-web-services - AWS 什么是 EC2 CPUCredits 以及如何标记它以使用成本管理和计费?
- javascript - SVG.js - 如何在 Angular 中访问 shadow-root(打开)中的元素
- python - 如何 serial.read_until 一个特定的字节值?
- javascript - 在无状态组件中对 material-ui 表单验证做出反应。反应钩子形式不起作用
- python - python中的pycrypto和crypto包有什么区别?
- c# - 如何在 Xamarin.Android 中将 DataTable 转换为 ListView 适配器
- angular - 禁用角度动态创建的多选(使用插件)下拉菜单