有时候阅读python代码的时候,会在第一句看到:
from __future__ import annotations
在Python中,from __future__ import annotations
这条语句用于从Python的未来版本中导入特性,具体来说,它允许你在类型注解(type annotations)中使用尚未定义的类名作为字符串字面量,而不是将它们当作前向引用(forward references)处理。这意味着,当你在类定义中使用类型注解来引用该类本身或其他尚未定义的类时,你不再需要使用字符串形式的类型注解(比如 'ClassName'
),而是可以直接使用类名。
在Python 3.7及更早版本中,如果你在类定义中直接使用类名作为类型注解,并且这个类名是在后面定义的(即尚未定义),那么解释器会抛出一个NameError
,因为它不知道这个类名是什么。为了解决这个问题,你可以使用字符串字面量来代替类名,或者使用特定的机制(如typing.TYPE_CHECKING
和typing.get_type_hints
)来在运行时避免这些错误。
从Python 3.7开始,from __future__ import annotations
被引入作为一个过渡性措施,允许开发者以更直观的方式编写类型注解,而不必担心类名未定义的错误。这个特性在Python 3.10中成为了默认行为,意味着在Python 3.10及更高版本中,即使不使用from __future__ import annotations
,你也可以直接在类型注解中使用尚未定义的类名。
我们来看一个例子,先定义类C,定义其中的函数时,在类型注释中使用了尚未定义的类名D:
>>> class C:
... def some_method(self, b: D) -> None:
... print(f"A is interacting with {b}")
...
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 2, in C
NameError: name 'D' is not defined
>>> from __future__ import annotations
>>> class C:
... def some_method(self, b: D) -> None:
... print(f"A is interacting with {b}")
...
>>>
可以看到,第一次定义C的时候报错,说D没有定义。
然后输入 from __future__ import annotations之后,再定义C的时候,就没有报错了。
总结:
为了解决类型注释未定义这个问题,Python 3.7及以上版本引入了一个特殊的from __future__ import annotations
语句。这个语句的作用是改变Python解释器处理类型注解的方式,使得类型注解中的字符串在运行时被当作字符串处理,而不是在定义时立即求值。这允许你在类定义之前使用尚未定义的类名作为类型注解,因为此时这些类型注解仅仅是字符串,不会立即被解释器评估。