Python 3.5类型注释变量无初始值

cro*_*ser 5 python typechecking python-3.5 mypy

我需要声明具有“复杂”类型的全局变量,并且不应在导入时实例化。在Python 3.6+中,我可以省略初始化,例如:

log: logging.Logger
pollset: select.poll
Run Code Online (Sandbox Code Playgroud)

我需要使代码与 Python 3.5 兼容。我可以使用评论类型注释:

log = ...  # type: logging.Logger
pollset = ...  # type: select.poll
Run Code Online (Sandbox Code Playgroud)

但随后我必须提供初始值。这在运行时不是问题,分配Noneor的初始值...就可以了。但其中任何一个都会触发 mypy 类型检查错误:

myprog.py:19:错误:赋值中的类型不兼容(表达式的类型为“省略号”,变量的类型为“Logger”)

当然我可以使用Optionaltype 来允许初始化为None,但是类型检查会被削弱。例如,None在代码中的其他地方给变量赋值是非法的,但它不会被捕获。

是否有一种可接受的方法以与 Python 3.5 兼容的方式使用变量的强类型检查?

Mic*_*x2a 1

您可以采用的一种技术是创建一个类型为 的虚拟变量Any,然后使用它而不是将变量设置为...None。例如:

from typing import Any

_bogus = None     # type: Any
log = _bogus      # type: logging.Logger
pollset = _bogus  # type: select.poll
Run Code Online (Sandbox Code Playgroud)

然而,这个解决方案并不完美。使用变量注释,我们避免了实际创建并为这些变量赋值,因此尝试log在实例化之前使用它会导致运行时出现 NameError。

然而,通过这种方法,我们会得到None,这与我们声明的类型相矛盾。

也许这适合您的用例,但如果不是,我们可以通过将它们粘贴在块内来获得更接近变量注释行为的内容if TYPE_CHECKING

from typing import Any, TYPE_CHECKING

if TYPE_CHECKING:
    _bogus = None     # type: Any
    log = _bogus      # type: logging.Logger
    pollset = _bogus  # type: select.poll
Run Code Online (Sandbox Code Playgroud)

TYPE_CHECKING变量在运行时始终为 False,但被 mypy 等类型检查器视为 True。

(这样做if False也有效。这是一个足够常见的约定,mypy 直接支持它作为使用的替代方案TYPE_CHECKING。)