是否可以将 Python 中的所有类型提示/检查基础结构分离到 .pyi 文件中?

Is it possible to separate all type hinting / checking infrastructure in Python into .pyi files?

使用 Python 3,类型提示允许 mypy 等第三方工具检查类型;但是,我发现类型检查语法与程序注释一起有点难看。使用 mypy 可以将存根函数和方法放入与 .py 文件相同的目录中的单独 .pyi 文件中。是否可以在 .py 文件的等效 .pyi 文件中定义所有与类型相关的语法?因此,例如,您可以使用所有类型语法在 .pyi 文件中定义变量、方法、return 类型等,但保留主要的 .py 代码?

不是真的。虽然 PEP 484 确实指定您可以创建自定义 pyi 文件,这些文件最终充当现有模块的 "public interface" 以使代码的任何用户受益,但它没有指定获取这些 pyi 文件和内部 typecheck相应的py文件。

事实上,如果一个目录同时包含py和pyi文件,则py文件将被完全忽略。

mypy issue tracker 上有一个开放的功能请求,但对我来说这似乎是一种低优先级的任务,因为即使实现了该功能,您最终也只能使用Python 类型系统的一个子集。

例如,假设我们想使用 NewType 之类的东西来编写一些用于模板化 HTML 或其他东西的代码:

from pathlib import Path
from typing import NewType

UnsanitizedText = NewType('UnsanitizedText', str)
CleanHtml = NewType('CleanHtml', str)
HtmlTemplate = NewType('HtmlTemplate', str)

def get_user_input() -> UnsanitizedText:
    # code omitted

def escape_to_html(raw: UnsanitizedText) -> CleanHtml:
    # perform checks on 'raw', do escaping logic, etc
    return CleanHtml(cleaned_string)

def load_template(path: Path) -> HtmlTemplate:
    return HtmlTemplate(path.read_text())

def render_template(template: HtmlTemplate, *kwargs: CleanHtml) -> CleanHtml:
    # code omitted

t = load_template(Path("foo/bar.html"))
dirty = get_user_input()
clean = escape_to_html(dirty)

print(render_template(t, arg=dirty))  # Does not typecheck
print(render_template(t, arg=clean))  # Typechecks

由于我们确实需要调用幻像新类型,我们 constructed/can 在正则表达式中混合和混合这些幻像调用,因此不清楚我们如何将此模块表示为存根。

还有一些其他类型的特征也很难在存根中表示——例如强制转换、NamedTuple、TypedDict 等