Python 中类型注解的自引用或前向引用 [英] Self-reference or forward-reference of type annotations in Python

查看:108
本文介绍了Python 中类型注解的自引用或前向引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图弄清楚类型的自引用如何与 python3 的类型注释一起使用 - 文档没有对此指定任何内容.

举个例子:

 from typing import TypeVar, Optional, GenericT = TypeVar('T')类节点(通用 [T]):左 = 无正确 = 无值 = 无定义 __init__(自我,价值:可选[T],左:可选[节点[T]]=无,右:可选[节点[T]]=无,) ->没有任何:self.value = 价值self.left = 左self.right = 正确

此代码生成错误:

回溯(最近一次调用最后一次):文件node.py",第 4 行,在 <module> 中类节点(通用 [T]):文件node.py",第 12 行,在 Node 中右:可选[节点[T]]=无,NameError:未定义名称节点"

这是使用 Python 3.5.1

解决方案

PEP 0484 - 类型提示 - 前向声明的问题 解决了这个问题:

<块引用>

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

...

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

 from typing import TypeVar, Optional, GenericT = TypeVar('T')类节点(通用 [T]):左 = 无正确 = 无值 = 无定义 __init__(自己,值:可选[T],左:可选['节点[T]']=无,右:可选['节点[T]']=无,) ->没有任何:self.value = 价值self.left = 左self.right = 正确

<小时><预><代码>>>>导入打字>>>Typing.get_type_hints(Node.__init__){'返回':无,'值':typing.Union[~T, NoneType],'left':typing.Union[__main__.Node[~T], NoneType],'正确':typing.Union[__main__.Node[~T], NoneType]}

I'm trying to figure out how self-reference of types work with python3's type annotations - the docs don't specify anything regarding this.

As an example:

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

This code generates the error:

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

This is using Python 3.5.1

解决方案

PEP 0484 - Type Hints - The problem of forward declarations addresses the issue:

The problem with type hints is that annotations (per PEP 3107 , and similar to default values) are evaluated at the time a function is defined, and thus any names used in an annotation must be already defined when the function is being defined. A common scenario is a class definition whose methods need to reference the class itself in their annotations. (More general, it can also occur with mutually recursive classes.) This is natural for container types, for example:

...

As written this will not work, because of the peculiarity in Python that class names become defined once the entire body of the class has been executed. Our solution, which isn't particularly elegant, but gets the job done, is to allow using string literals in annotations. Most of the time you won't have to use this though -- most uses of type hints are expected to reference builtin types or types defined in other modules.

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]}

这篇关于Python 中类型注解的自引用或前向引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆