Python中类型注释的自引用或前向引用[重复]

Posted

技术标签:

【中文标题】Python中类型注释的自引用或前向引用[重复]【英文标题】:Self-reference or forward-reference of type annotations in Python [duplicate] 【发布时间】:2016-07-11 15:37:42 【问题描述】:

我正在尝试弄清楚类型的自引用如何与 python3's type annotations 一起使用 - 文档没有对此进行任何说明。

举个例子:

from typing import TypeVar, Optional, Generic

T = TypeVar('T')
class Node(Generic[T]):
    left = None
    right = None
    value = None

    def __init__(
        self, value: Optional[T],
        left: Optional[Node[T]]=None,
        right: Optional[Node[T]]=None,
    ) -> None:
        self.value = value
        self.left = left
        self.right = right

此代码生成错误:

Traceback (most recent call last):
  File "node.py", line 4, in <module>
    class Node(Generic[T]):
  File "node.py", line 12, in Node
    right: Optional[Node[T]]=None,
NameError: name 'Node' is not defined

这是使用 Python 3.5.1

【问题讨论】:

嗯,typing 仅从 3.5 开始可用。检查whatsnew of 3.5 version @thefourtheye:我编辑了这个问题。我刚刚安装了3.5.1,问题依旧存在。我使用 3.4 的原因是因为我安装了 mypy 【参考方案1】:

PEP 0484 - Type Hints - The problem of forward declarations 解决了这个问题:

类型提示的问题在于注释(根据 PEP 3107 和 类似于默认值)在函数执行时进行评估 已定义,因此注释中使用的任何名称必须已经 在定义函数时定义。一个常见的场景是 类定义,其方法需要引用类本身 他们的注释。 (更一般地说,它也可以相互发生 递归类。)这对于容器类型来说是很自然的,例如:

...

由于 Python 的特殊性,这行不通 一旦类的整个主体都定义了类名 被执行。 我们的解决方案,不是特别优雅,但是 完成工作,就是允许在注释中使用字符串文字。 大多数时候你不必使用它——大多数使用 类型提示应该引用内置类型或定义的类型 其他模块。

from typing import TypeVar, Optional, Generic

T = TypeVar('T')
class Node(Generic[T]):
    left = None
    right = None
    value = None

    def __init__(
        self,
        value: Optional[T],
        left: Optional['Node[T]']=None,
        right: Optional['Node[T]']=None,
    ) -> None:
        self.value = value
        self.left = left
        self.right = right

>>> import typing
>>> typing.get_type_hints(Node.__init__)
'return': None,
 'value': typing.Union[~T, NoneType],
 'left': typing.Union[__main__.Node[~T], NoneType],
 'right': typing.Union[__main__.Node[~T], NoneType]

【讨论】:

谢谢!我不敢相信我完全错过了那部分 - 它甚至有一个与我类似的例子! 那么字典自引用本身呢?例如 MyDict=TypedDict('MyDict','callback': Callable[[MyDict], None] 我想要做的是在字典中添加一个键/值,该值是一个回调函数,作为第一个参数MyDict 本身 ... 我不知道,但这种情况令人失望,我认为这样的解决方法对于让自动完成工作有点太多了。我们不能为此使用好的旧文档字符串吗? ***.com/a/62227759/1312695 @user1312695,你可以。但是你会丢失类似 mypy 的工具检查。 @user1312695,如果您使用的是 Python 3.7+,from __future__ import annotations 将允许您使用“可选[Node[T]]”。 python.org/dev/peps/pep-0563

以上是关于Python中类型注释的自引用或前向引用[重复]的主要内容,如果未能解决你的问题,请参考以下文章

前向声明 boost.type_erasure 引用类型

python 前向引用

Django模型:两个类之间的相互引用以及在python中无法使用前向声明

Python之函数参数局部全局变量前向引用递归

JS基础

我在.net中添加了一个引用,怎么把这个引用删除、我只是在项目中找到了添加引用项。但是怎么删除呢