【问题标题】:Name not defined in type annotation [duplicate]类型注释中未定义名称[重复]
【发布时间】:2016-07-17 03:52:47
【问题描述】:

我目前正在创建一个 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)?

【问题讨论】:

  • 请将您的帖子限制为每个帖子一个问题。这里有两个不同的问题,一个是关于循环依赖(类的方法取决于创建之前的类),以及类型和类之间的区别。后者是重复的。
  • 请参阅Class vs. Type in Python,了解我从您的帖子中删除的部分问题。
  • 对不起。我认为类型问题与手头的问题有关。

标签: python python-3.x type-hinting python-typing


【解决方案1】:

你有一个前向声明;函数(作为方法绑定)是在类创建之前创建的,因此名称Vector 尚不存在。只有当所有的类体都执行完毕后,Python 才能创建class 对象并将名称Vector 绑定到它。

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

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

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

另见specification on forward references

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

[...]

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

从 Python 3.7 开始,您可以通过在模块顶部添加 from __future__ import annotations 指令,使给定模块中的所有注解都表现得像前向注解(无需将它们括在字符串文字中)。在 Python 3.10 及更高版本中 this has become the default behaviour。见PEP 563 -- Postponed Evaluation of Annotations。请注意,在注释之外,您可能仍需要使用前向引用语法(字符串文字),例如在类型别名中(就 Python 而言,这是一个常规变量赋值)。

【讨论】:

  • 谢谢。我在链接的问题中看到了字符串答案,但让我失望的是它用类颜色突出显示other: Vector,而没有用类颜色突出显示-> Vector,所以当我评论后一个向量时,我从不认为我需要这样做对于前者。感谢您的澄清。
【解决方案2】:

如果您使用的是 Python 3.7 及更高版本。看看Postponed evaluation of annotations

从Python 3.7开始就允许了,只需要添加:

from __future__ import annotations

还要注意

它将成为 Python 3.10 中的默认设置。

【讨论】:

  • 这很有趣。我将按原样保留答案,因为它适用于所有 3.x 版本(或者至少,比 import annotations 解决方案更多的 3.x 版本),但我仍然很高兴你在这里发布了这个。
  • 确保您将此行作为模块的第一行输入。
  • @VladBezden 当然,正如 pep8 所建议的那样:文件顶部的导入和 未来 优先。
  • 对于 Python 3.6,我收到错误 future feature annotations is not defined
  • @ShitalShah 是的,因为它是 Python 3.7.x - 4.0 的一个功能,正如答案中所说。
猜你喜欢
  • 2022-12-16
  • 1970-01-01
  • 2017-09-14
  • 2021-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多