将当前类作为返回类型注释

sas*_*hka 93 python annotations class python-3.x

在python 3中,我可以创建参数并返回类型注释.例:

class Graph:
    def __init__(self, V: int, E: int, edges: list):
        pass

    @classmethod
    def fromfile(cls, readobj: type(sys.stdin)):
        pass

    def V(self) -> int:
        pass

    def E(self) -> int:
        pass
Run Code Online (Sandbox Code Playgroud)

问题是我无法使用当前类(Graph)的返回类型进行注释,该类尚未定义.例:

class Graph:
   def reverse(self) -> Graph:
       pass
Run Code Online (Sandbox Code Playgroud)

此代码有错误

def reverse(self) -> Graph:
NameError: name 'Graph' is not defined
Run Code Online (Sandbox Code Playgroud)

这些注释对于记录和允许IDE识别参数和返回类型=>启用自动完成非常有用

UPD:所以我提出的是要么是不可能的要么是需要一些我不喜欢的黑客攻击,所以我决定使用def reverse (self) -> 'Graph': 哪种文档是可以理解的,尽管违反了规则.缺点是它不适用于IDE自动完成.

sas*_*hka 64

所以现在过了一段时间我可以说我采取的决定是用-> 'Graph'而不是-> Graph.它不会使我的IDE(PyCharm)能够以这种方式识别类型,但它只是用于文档目的.

我可以使用的另一个可能的解决方案是在运行时更改注释,但这并不能解决文档中的问题 - 您不希望在源代码中找到类型声明...

问题的根源在于在实际定义类之前识别类对象.这在python中根本不可能.

  • 实际上,这是一个正确的解决方案,称为前向引用 - https://www.python.org/dev/peps/pep-0484/#forward-references.当前版本的PyCharm(在撰写本评论时)认识到这是一种典型的写作,并提供所有必要的支持. (38认同)
  • 2020 年更新 - PyCharm 现在可以识别 `-> 'Graph'` 格式的类型 - 您可以 CMD+Click 转到定义等 (3认同)

Kas*_*mvd 40

在python-3.7中,通过不在函数定义时评估注释来解决此问题.相反,它们__annotations__以字符串形式保存.这称为PEP 563中引入的延迟评注注释.

另请注意:

弃用政策

从Python 3.7开始,需要__future__导入才能使用所描述的功能.没有提出任何警告.

在Python 3.8中PendingDeprecationWarning,编译器在没有__future__ 导入的模块中存在类型注释时引发了.

从Python 3.9开始,警告变成了一个DeprecationWarning.

在Python 4.0中,这将成为默认行为.不再支持使用与此PEP不兼容的注释.

这是一个例子:

In [7]: from __future__ import annotations

In [8]: class C:
   ...:     def func(cls, arg:str) -> C:
   ...:         pass
   ...:     

In [9]: c = C()
Run Code Online (Sandbox Code Playgroud)

  • 尽管这个问题非常古老并且原作者回答了自己,但我会将这个答案作为一个可接受的答案。 (6认同)