Mypy 错误 - 分配中的类型不兼容
Posted
技术标签:
【中文标题】Mypy 错误 - 分配中的类型不兼容【英文标题】:Mypy error - incompatible types in assignment 【发布时间】:2017-10-10 04:40:01 【问题描述】:我的函数看起来像这个简化的代码示例:
def my_func() -> dict:
result = "success": False
if condition:
result["success"] = True
return result
else:
result["message"] = "error message"
return result
当我运行 Mypy(0.52 版)时,我收到此错误:
error: Incompatible types in assignment (expression has type "str", target has type "bool")
并且错误指向我的代码示例中的倒数第二行。 为什么 mypy 返回此错误?我的代码是无效的(以任何方式)还是这是一些 mypy 错误?
【问题讨论】:
【参考方案1】:问题在于 mypy 推断出您的 result
变量的类型是 Dict[str, bool]
,这是由于您在第 2 行首次对其进行初始化的方式。
因此,当您稍后尝试插入 str 时,mypy(理所当然地)抱怨。您有几个选项可以修复您的代码,我将按照类型安全从低到高的顺序列出这些选项。
选项 1 是声明您的字典,使其值的类型为 Any
- 也就是说,您的值根本不会进行类型检查:
from typing import Any, Dict
def my_func(condition: bool) -> Dict[str, Any]:
result = "success": False # type: Dict[str, Any]
if condition:
result["success"] = True
else:
result["message"] = "error message"
return result
请注意,我们需要对您的第二行进行注释,以便向 mypy 提示 result
的类型应该是什么,以帮助其推理过程。
如果您使用的是 Python 3.6+,则可以使用以下替代语法来注释该行,该语法使用变量注释(自 Python 3.6 起新增):
result: Dict[str, Any] = "success": False
选项 2 的类型安全性稍高一些——使用 Union
将值声明为 strs 或 bools,但仅此而已。这不是完全类型安全的,但至少您仍然可以对您的 dict 进行 一些 检查。
from typing import Any, Dict
def my_func(condition: bool) -> Dict[str, Union[str, bool]]:
result = "success": False # type: Dict[str, Union[str, bool]]
if condition:
result["success"] = True
else:
result["message"] = "error message"
return result
您可能会发现类型注释有点长/令人讨厌,因此您可以使用类型别名来提高可读性(并且可以选择使用变量注释语法),如下所示:
ResultJson = Dict[str, Union[str, bool]]
def my_func(condition: bool) -> ResultJson
result: ResultJson = "success": False
# ...snip...
选项 3 是最安全的,尽管它确实要求您使用实验性的 'TypedDict' 类型,它允许您将特定类型分配给 dict 中的不同字段。也就是说,使用这种类型需要您自担风险——AFAIK 它尚未添加到 PEP 484,这意味着其他类型检查工具(如 Pycharm 的检查器)没有义务理解这一点。 Mypy 本身最近才添加了对 TypedDict 的支持,因此可能仍然存在问题:
from typing import Optional
from mypy_extensions import TypedDict
ResultJson = TypedDict('ReturnJson', 'success': bool, 'message': Optional[str])
def my_func(condition: bool) -> ResultJson:
result = "success": False, "message": None # type: ResultJson
if condition:
result["success"] = True
else:
result["message"] = "error message"
return result
如果您想使用此选项,请务必安装 mypy_extensions
软件包。
【讨论】:
感谢迈克尔的全面回答!我想我在 mypy 逻辑的某些概念上遇到了困难,但你真的为我澄清了这一点。旁注:当行长度超过 PEP8 允许的 79 个字符时,您知道如何处理内联类型提示 cmets 吗? (这个项目我不能用Python3.6,所以新的变量注解语法对我不可用) @JanRozycki 小心使用type aliases 通常可以帮助缓解这个问题。在键入具有许多参数的函数时,键入您的函数 like this 也很有帮助。TypedDict
在 python 3.8 中被添加到标准库中以上是关于Mypy 错误 - 分配中的类型不兼容的主要内容,如果未能解决你的问题,请参考以下文章
mypy 错误:返回值类型不兼容(得到“object”,预期“Dict [Any, Any]”)