Python 类型提示兼容性

Python type hinting compatibility

我正在编写处理 Python AST 节点的代码,它应该兼容 Python 2 和 Python 3。

然而,Python 3 有 ast.Try,其中 Python 2 有 ast.TryFinallyast.TryExcept,所以我需要使用 visit_处理这两种情况的别名。

如果我使用兼容性别名编写我的节点访问者代码,如下所示,我的预提交 mypy 检查在使用 Python 2 时会报错,即 error: Name 'ast.Try' is not defined:

import ast

class Visitor(ast.NodeVisitor):


    def visit_Try(self, node):  # type: (ast.Try) -> None
        ...
    visit_TryFinally = visit_Try  # python 2 compatible

如果我在类型提示中使用 ast.TryFinally,如果我在 Python 中 运行 它会抱怨 error: Name 'ast.TryFinally' is not defined 3. 我知道我可以使用节点的更通用类型,但这让我在代码中写了很多我不想要的 # type: ignore

我该如何解决这个问题?

Mypy 知道 how to handle Python version checks,您可以使用条件 类型别名 为正确的 Python 版本选择正确的类型:

if sys.version_info[0] >= 3:
    TryNode = ast.Try
else:
    TryNode = ast.TryFinally

class Visitor(ast.NodeVisitor):


    def visit_Try(self, node):  # type: (TryNode) -> None
        # ...
    visit_TryFinally = visit_Try  # python 2 compatible

您可以通过将代码放在 if TYPE_CHECKING: test.

中进一步节省 if sys.version_info 测试的运行时间成本

附带说明:如果您在 Python 3 中处理 ast.Try 以跟踪 try 语句的 finally:except ...: 组件,你想在 Python 2 中同时处理 ast.TryFinallyast.TryExcept,和以前的 Python 2.5 一样,你只能使用 try...finally try...except 在一个语句中。