首页 > 解决方案 > 如何注释返回 self 的方法,以便存根文件显示正确的返回类型?

问题描述

借口:这段代码没用,用例也可能没用,但我只是想弄清楚如何使它工作,以便存根文件显示正确的签名。这个问题似乎令人困惑,所以我正在尽力解释,但我非常愿意接受使问题结构更好的建议。

环境:Python:3.7.9 Mypy Vscode + Pylance

目录结构:

 .
├──  1.py
└──  testcode
   ├──  __init__.py
   └──  modules
      ├──  __init__.py
      └──  something.py

里面1.py

from testcode import Entry

e = Entry('a').a_function().b_function().c_function()

里面__init__.py

from .modules.something import Something, AnotherThing

class Entry(Something, AnotherThing):
    def __init__(self, a: str):
        self.a = a

在这种情况下,return self是 的实例Entry。当我没有在b_function(或 a、b、c 函数)中指定返回类型时,类型提示是正确的。

在此处输入图像描述

但是当我将返回类型指定为 时Entry,返回类型显示为Any

something.py带有注释的返回类型:

class Something(object):
    def a_function(self) -> 'Entry':
        return self

    def b_function(self) -> 'Entry':
        return self

class AnotherThing:
    def c_function(self) -> 'Entry':
        return self

在此处输入图像描述

因此,为了尝试克服这个问题,我尝试使用创建所有文件stubgen的命令创建存根文件,其中包括:stubgen -o . -p testcodepyisomething.pyi

class Something:
    def a_function(self) -> Entry: ...
    def b_function(self) -> Entry: ...

class AnotherThing:
    def c_function(self) -> Entry: ...

存根生成后的目录:

 .
├──  1.py
└──  testcode
   ├──  __init__.py
   ├──  __init__.pyi
   └──  modules
      ├──  __init__.py
      ├──  __init__.pyi
      ├──  something.py
      └──  something.pyi

现在我明白了为什么这不起作用,因为当我Entry在方法中指定返回类型时Something,python 不知道Entry在下一个屏幕截图中可以看到什么。所以它将Any类型分配给它:

在此处输入图像描述

问题:

知道当Entry方法的返回类型未在 for 中注释时Something,它会选择正确的返回类型(因此提供了很好的智能感知),我如何正确注释和生成存根文件,以便Any当返回类型为 self 时它不会返回注释?

编辑:

反思第一个答案,绑定子类并不能完全解决问题,因为智能感知和类型将仅显示调用的方法方法。例如,如果我调用a_functionc_function将不会显示,反之亦然。当我没有在SomethingandAnotherThing类的返回类型上键入提示,并且 vscode 正确假设是返回类型时,我可以在调用时Entry获得智能感知c_functiona_function

在此处输入图像描述

标签: pythonmypypython-typing

解决方案


解决方案是使self您的参数SomethingAnotherThing函数绑定到这些类的子类,TypeVar如下所示:

from typing import TypeVar


ST = TypeVar('ST', bound='Something')

class Something:
    def a_function(self: ST) -> ST:
        return self

    def b_function(self: ST) -> ST:
        return self

AT = TypeVar('AT', bound='AnotherThing')

class AnotherThing:
    def c_function(self: AT) -> AT:
        return self

更多信息可以在这里找到。


推荐阅读