名称未在类型注释中定义

Mut*_*pus 30 python type-hinting python-3.x

我正在创建一个python线性代数模块,用于娱乐和练习语言.我最近尝试向模块添加类型注释,如下所示:

class Vector:
     # Various irrelevant implementation details
     def __add__(self, other: Vector) -> Vector:
        # More implementation details....
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试导入它时,它会吐出一个NameError: Name 'Vector' is not defined.我承认这个问题已经在这里以一种形式得到了回答,但它似乎并没有完全为我的情况提供答案.

我想知道的是什么:

  • 我已经在这个文件中逐字地定义了这个类.为什么说这个名字没有定义?
  • 如何Vector以这样的方式定义它可以用于注释(作为a type)?

Mar*_*ers 44

你有前瞻性声明; 函数(作为方法绑定)是之前创建的,因此名称Vector尚不存在.只有当所有类主体都已执行时,Python才能创建class对象并将名称绑定Vector到它.

只需使用带有名称的字符串:

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

这不会影响IDE查看声明的方式; 加载整个模块后,将查找字符串,并在当前上下文中将其解析为有效的Python表达式.由于在Vector加载整个模块后类存在,因此'Vector'可以将字符串正确转换为类对象.

另请参阅前向参考规范:

当类型提示包含尚未定义的名称时,该定义可以表示为字符串文字,稍后要解决.

[...]

字符串文字应该包含一个有效的Python表达式[...],一旦模块完全加载,它应该在没有错误的情况下进行评估.


vis*_*ell 19

如果您使用的是Python 3.7及更高版本.看一下延期的注释评估

从Python 3.7开始,它将被允许,只需添加:

from __future__ import annotations
Run Code Online (Sandbox Code Playgroud)

并且还要注意

它将成为Python 4.0的默认设置.

  • 注意到这一点很有趣。我将保留答案,因为它适用于所有 3.x 版本(或者至少,比“导入注释”解决方案更多的 3.x 版本),但我仍然很高兴你在这里发布了这个。 (2认同)