类型注释中未定义名称[重复]

问题描述 投票:0回答:2

我目前正在创建一个 Python 线性代数模块,以供娱乐和练习该语言。我最近尝试向模块添加类型注释,如下所示:

class Vector:
     # Various irrelevant implementation details
     def __add__(self, other: Vector) -> Vector:
        # More implementation details....

但是,当我尝试导入它时,它会吐出一个

NameError: Name 'Vector' is not defined
。我承认这个问题已经以here的形式得到了回答,但它似乎并没有完全为我的情况提供答案。

我想知道的是:

  • 我已经在这个文件中按字面定义了该类。为什么说名称未定义?
  • 如何定义
    Vector
    使其可用于注释(作为
    type
    )?
python python-3.x type-hinting python-typing
2个回答
109
投票

您有前瞻性声明;函数(作为方法绑定)是在类创建之前创建的,因此名称 Vector 尚不存在。只有当所有类体都被执行后,Python 才能创建

class
对象并将名称
Vector
绑定到它。
只需使用带有名称的字符串即可:

class Vector: # Various irrelevant implementation details def __add__(self, other: 'Vector') -> 'Vector': # More implementation details....

这不会影响您的 IDE 如何查看声明;加载整个模块后就会查找字符串,并将其解析为当前上下文中的有效 Python 表达式。由于类 
Vector

在整个模块加载后就存在,因此字符串

'Vector'
可以正确地转换为类对象。
另请参阅

有关前向引用的规范

当类型提示包含尚未定义的名称时,该定义可能会表示为字符串文字,稍后再解析。

[...]

字符串文字应包含有效的 Python 表达式 [...],并且一旦模块完全加载,它的计算结果应该不会出现错误。

从 Python 3.7 开始,您可以通过在模块顶部添加
from __future__ import annotations

指令,使给定模块中的所有注释都表现得像前向注释(无需将它们包含在字符串文字中)。最初计划将此设置为 Python 3.10 及更高版本中的默认设置,但此决定现已无限期推迟。有关详细信息,请参阅

PEP 563 -- 
推迟的注释评估。请注意,注释的outside您可能仍然需要使用前向引用语法(字符串文字),例如在类型别名中(就 Python 而言,这是常规变量赋值)。


57
投票

在 Python 3.7 到 3.12 中,您可以将以下内容添加到文件的开头:

from __future__ import annotations

请参阅
PEP 649

了解更多详情。

© www.soinside.com 2019 - 2024. All rights reserved.