Python 输入 - 如果是 None,有没有办法避免导入可选类型?

Python typing - is there a way to avoid importing of optional type if it's None?

假设我们有这样一个函数定义:

def f(*, model: Optional[Type[pydantic.BaseModel]] = None)

因此,在您将某些内容作为 model 传递之前,该函数不需要安装 pydantic。现在假设我们要将函数打包到 pypi 包中。我的问题是,是否有一种方法可以避免仅仅为了类型检查而将 pydantic 引入包依赖项?

Python 的 typing 模块可以使用字符串类型名称,以及类型本身,就像您在示例中使用的那样。

如果您不想在代码为运行时评估类型,并且在模块未导入时抛出异常,那么您可能更喜欢使用字符串名称。您的代码片段将是:

def f(*, model: Optional[Type["pydantic.BaseModel"]] = None)

您使用 mypy 的静态类型检查应该会继续工作,但您的包将不再总是需要对 pydantic.

的依赖

正如您在 docs 中发现的那样,python 的 typing 模块包含一种方法来指定某些导入仅对于(字符串文字)类型注释是必需的:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    import pydantic

这只会在TYPE_CHECKINGTrue时执行import pydantic语句,主要是在使用mypy分析代码中的类型时。 运行程序正常运行时,import语句不执行。因此,该选项只能与字符串文字类型提示一起使用;否则,缺少导入将导致程序无法正常执行。

由于 延迟评估 类型提示将在 Python 4.0 中实现,

from __future__ import annotations

可用于在 Python 3 中启用此行为。使用此导入语句,不需要字符串文字类型。

我会做类似的事情

try:
    from pydantic import BaseModel as PydanticBaseModel
except ImportError:
    PydanticBaseModel = None

我不认为它比 更好,但有时一些奇怪的风格指南可能会禁止您使用字符串类型名称,所以我只是想指出另一个解决方案。

我尝试遵循 , but I found mypy still giving me Name 'pydantic' is not defined error. Then I found this chapter in the docs,它似乎也适用于我的情况:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    import pydantic

您可以在 __future__.annotations (python 3.8.1) 中使用普通类(而不是字符串文字):

from __future__ import annotations

from typing import TYPE_CHECKING, Optional, Type

if TYPE_CHECKING:
    import pydantic


def f(*, model: Optional[Type[pydantic.BaseModel]] = None):
    pass

如果由于某种原因您无法使用 __future__.annotations,例如您使用的是 python < 3.7,请使用 .

中的字符串文字进行键入