包对象的 Python 前向引用

A. *_*dry 2 python type-hinting python-3.x python-typing

我怀疑答案是肯定的,但我想问清楚。例如,如果我有一个函数需要使用一个numpy对象,但我没有numpy直接在我的模块中使用,我可以使用前向引用来键入提示我的参数而不是numpy直接导入吗?

换句话说(假设Python 3.7+),我可以这样做吗

# forward-reference.py

def my_func(arr: "np.ndarray") -> int:
    # does some operations with arr
Run Code Online (Sandbox Code Playgroud)

而不是这个

# direct-import.py

import numpy as np

def my_func(arr: np.ndarray) -> int:
    # do some operations on arr...
Run Code Online (Sandbox Code Playgroud)

我无法想象核心开发人员会要求程序员仅仅为了类型提示而导入模块。我pylint的或flake8linter 会正确地将它们拾取为未使用的模块,我认为所有这些额外的导入将是相当多余的。

编辑

为了测试,我创建了两个文件:demo1.pydemo2.py(都位于同一目录中):

演示1.py

# demo1.py

import numpy as np

from demo2 import my_func

if __name__ == "__main__":
    a = np.array([1, 2, 3])
    print(my_func(a))
Run Code Online (Sandbox Code Playgroud)

演示2.py

# demo2.py

def my_func(arr: "np.ndarray") -> int:
    return arr[0]
Run Code Online (Sandbox Code Playgroud)

运行mypy不会出现错误,但使用其中之一demo1.py运行会出现错误:demo2.pynumpy.ndarray

demo2.py:1: error: Name "numpy" is not defined
Run Code Online (Sandbox Code Playgroud)

np.ndarray给出错误:

demo2.py:1: error: Name "np" is not defined
Run Code Online (Sandbox Code Playgroud)

因此,如果我首先设计一个模块demo2.py,并希望它在设计之前接受 numpy 数组demo1.pymypy则会出现错误。

有没有更好/“正确”的方法来处理上述情况?

AKX*_*AKX 5

不,你不能。

您需要在范围内包含名称(毕竟,您可以完成 Ministry of Silly Imports 并完成),但如果您不想真正导入模块,则import math as np可以使用:typing.TYPE_CHECKING

from typing import TYPE_CHECKING

if TYPE_CHECKING:  # never true unless you're a type checker
    import numpy as np

def my_func(arr: "np.ndarray") -> int:
    pass  # does some operations with arr
Run Code Online (Sandbox Code Playgroud)

除此之外,类型检查器不(或不应该)关心你如何称呼这些东西;他们会以其最佳能力解析符号,例如这应该有效:(但请不要......)

from typing import TYPE_CHECKING

if TYPE_CHECKING:  # never true unless you're a type checker
    import numpy as noooooooooop
    bazoop = noooooooooop.ndarray
    glerp = int

def my_func(arr: "bazoop") -> "glerp":
    pass  # does some operations with arr
Run Code Online (Sandbox Code Playgroud)