MyPy - 处理可能的 None 返回类型

Ric*_*d B 2 python types python-3.x mypy

可能令我羞愧的是,我刚刚开始在我的 python 代码中包含类型检查。大多数类型检查都是直接进行的,但我对处理可以返回 None 的函数的 pythonic 方式有点迷失

例如

threads = os.cpu_count() * 1.2
Run Code Online (Sandbox Code Playgroud)

这会引发 MyPy 错误

Mypy: Unsupported operand types for * ("None" and "float")
Run Code Online (Sandbox Code Playgroud)

所以为了摆脱这个我将代码更改为

default = (os.cpu_count() if os.cpu_count() is not None else 1.0) * 1.2
Run Code Online (Sandbox Code Playgroud)

但这给出了完全相同的错误。

处理这个问题的最佳方法是什么?

小智 5

您的原始代码没有\xe2\x80\x99t 通过 mypy 因为您对同一函数有两次不同的调用,并且每次返回不同的Optional[int]. 缩小一个类型的范围不会影响另一个类型的类型。考虑这个极端的情况:

\n\n
import random\n\ndef maybe_an_int() -> Optional[int]:\n    if random.random() > 0.9:\n        return 1\n    return None\n\ndefault = (maybe_an_int() if maybe_an_int() is not None else 1.0) * 1.2\n\n
Run Code Online (Sandbox Code Playgroud)\n\n

如果第一次调用是\xe2\x80\x99t None,我们再次调用它。但显然,由于返回类型是随机的,我们无法预测第二次调用的返回类型是什么。

\n\n

许多代码库都有不同的方法来处理这个问题。一种选择是这样的:

\n\n
from typing import TypeVar\n\nT = TypeVar('T')\n\ndef default_optional(value: Optional[T], default: T) -> T:\n    if value is None:\n        return default\n    return value\n
Run Code Online (Sandbox Code Playgroud)\n