发生这种情况是因为在当前版本的 Python 中,注释在解释器首次评估签名时被解析。这意味着此时值需要是可解析的。
您想要做的称为“前向引用”。为了使前向引用成为可能,Python 正在积极改变解析注释的方式,并将这项工作转移到以后所有引用都可以解析的时候。
在解析注释之前的时间里,值被存储为简单的字符串。像 mypy 这样的库或像 pycharm 这样的工具今天已经能够处理这个问题了。
所以你有三个选择:
- 重构以避免前向引用
- 定义注释时明确使用字符串
- 使用
__future__ 模块启用未来行为。
选项 1: 重新排序类以在引用之前定义 B。这并不总是可行的,具体取决于布局。
class B:
pass
class A:
def funct_one(self, name: str, rec: B) -> None:
pass
选项 2: 使用注释的字符串版本。 mypy 或 pycharm 等工具将为您解析对真实类的引用。
class A:
def funct_one(self, name: str, rec: "B") -> None:
pass
class B:
pass
选项 3:(这是我的首选选项)通过导入未来的注释功能来使用延迟的注释处理。在这种模式下,我们可以轻松地在类型提示中对尚未定义的事物进行前向引用
from __future__ import annotations
class A:
def funct_one(self, name: str, rec: B) -> None:
pass
class B:
pass
警告:一些进行注释处理的库依赖于旧的实现,但对于简单的代码,这可以正常工作。这最终将是默认情况下 python 的操作方式,并且不需要 __future__ 导入。