我有一个函数返回一个class instance或None依赖于某些逻辑。\n在代码的某些地方我知道这个函数肯定不会返回None,\n但 mypy 抱怨。
我做了一个最小的例子来重现上述情况。
\n\n我想避免标记a_string为,我\n知道我也可以使用或a_string: Optional[str] = ""克服问题,但不知何故我\n觉得可能有更好的方法。casttype ignore
有什么建议如何处理这种情况?
\n\n对于这个例子,我使用mypy 0.641和python 3.7
"""\nFunction returns either an object or none\n\n"""\n\nfrom typing import Optional, cast\n\nRET_NONE = False\n\n\ndef minimal_example() -> Optional[str]:\n if RET_NONE:\n return None\n else:\n return "my string"\n\n\na_string = ""\nmaybe_string = minimal_example()\na_string = maybe_string\n\n# mypy doesn\'t complain if I do the following\na_string = cast(str, maybe_string)\na_string = maybe_string # type: ignore\nRun Code Online (Sandbox Code Playgroud)\n\nMypy 抱怨如下:
\n\n\xe2\x9d\xaf\xe2\x9d\xaf\xe2\x9d\xaf mypy mypy_none_or_object.py (chatsalot) \xe2\x9c\x98 1\nmypy_none_or_object.py:19: error: Incompatible types in assignment (expression has type "Optional[str]", variable has type "str")\nRun Code Online (Sandbox Code Playgroud)\n
Mic*_*x2a 14
Mypy 旨在将函数签名视为“事实来源”。如果您指出某个函数返回一个Optional[str],那么 mypy 将假定情况始终如此。它不会尝试查看任何全局变量如何改变或不改变该函数签名。
解决此问题最简单的方法是添加assert或isinstance检查:
maybe_string = minimal_example()
reveal_type(maybe_string) # Revealed type is Optional[str]
assert maybe_string is not None # Or use 'if isinstance(maybe_string, str)
reveal_type(maybe_string) # Revealed type is str
Run Code Online (Sandbox Code Playgroud)
(如果您不知道,mypy 会对该函数进行特殊处理reveal_type(...):每当 mypy 遇到它时,mypy 都会打印出您提供的任何表达式的类型。这对于调试很有用,但是您应该记住在使用后删除伪函数已完成,因为它在运行时不存在。)
或者,您可以重新设计代码,以便函数的返回值更加规范化——它始终返回一个字符串,而不是有时返回一个字符串。
如果RET_NONEis 是一个或多或少不可变的全局变量(例如“启用调试模式”或“假设我们在 Windows 上运行”),您可以使用 is 来利用 mypy 和--always-trueflags--always-false并提供两个不同的定义的minimal_example。例如:
RET_NONE = False
if RET_NONE:
def minimal_example() -> None:
return None
else:
def minimal_example() -> str:
return str
Run Code Online (Sandbox Code Playgroud)
mypy --always-true RET_NONE然后,您可以使用或 来调用 mypymypy --always-false RET_NONE以匹配变量的定义方式。您可以在此处或此处找到有关这些类型的更多信息。
您可以探索的第四种选择是使用函数重载:https://mypy.readthedocs.io/en/latest/more_types.html#function-overloading
但是,我不知道这是否真的适用于您的情况:您无法定义仅返回类型不同的重载:每个重载的参数数量或类型需要以某种方式彼此区分。
两种解决方案:cast()和# type: ignore都有效地关闭了 mypy 对变量的检查。这可能会掩盖错误,应尽可能避免。
在您的情况下, mypy 无法知道 的值RET_NONE,因为它可以在运行时更改为False其他任何值,因此会出现错误。
我建议添加一个断言:
a_string = ""
maybe_string = minimal_example()
assert maybe_string is not None # <- here
a_string = maybe_string
Run Code Online (Sandbox Code Playgroud)
现在 mypy 确信下一行maybe_string绝对不会是None. 我在有关类型的博客文章的约束类型部分中介绍了这一点。
| 归档时间: |
|
| 查看次数: |
15089 次 |
| 最近记录: |