是否可以让 Python IDE 为动态生成的类属性提供自动完成功能?

Is it possible to have Python IDEs offer autocompletion for dynamically generated class attributes?

提问人:CiaranWelsh 提问时间:8/16/2020 最后编辑:jonrsharpeCiaranWelsh 更新时间:8/29/2020 访问量:3907

问:

我可以使用任何技巧来让 IDE 为动态生成的类属性提供代码完成?例如


class A:
    
    def __init__(self):
        setattr(self, "a", 5)

此代码将 调用的 class 属性设置为 的值。但是 IDE 不知道,因此您不会获得它的代码完成。我读过该方法可以上钩,但该答案中提出的建议对我不起作用。有人有什么想法吗?Aa5a__dir__

Python 自动完成 属性

评论

2赞 roganjosh 8/16/2020
我也不太确定投反对票。我的直觉是,你的问题的答案是否定的,因为静态分析在这里看不到任何东西,但是,嘿,JIT是一回事,也许有一些聪明的IDE魔术可以做到这一点
0赞 CiaranWelsh 8/16/2020
我的想法也是,但如果有一个黑客来解决这个问题,那就太好了。也许有一个 Python 向导可以帮助我:)
0赞 jonrsharpe 8/17/2020
哪些 IDE?还有哪些其他限制?(例如,您可以使用像 ?文档字符串?a: int
0赞 CiaranWelsh 8/22/2020
我使用 Pycharm,但与其他人一起工作也会很有趣。是的,允许使用类型注释...事实上,我对任何想法都感兴趣。我遇到过几次这个问题,想知道是否存在任何策略,无论需要哪种工具(如类型注释)。感谢您的回复。

答:

14赞 igrinis 8/26/2020 #1

相信你会在这里找到答案。简而言之,Pycharm 目前不支持动态属性(而且可能在可观察到的未来不会)支持动态属性。这是因为它静态地分析代码,并且无法“看到”类可能具有的属性。另一方面,当您在(例如)iPython 中运行代码时,一旦创建了此类的实例,编辑器就可以获取驻留在内存中的特定实例的属性,从而在自动完成中显示它们。在这种情况下会有所帮助。我认为其他 IDE 也是如此。__dir__

因此,如果您确实需要自动完成功能,您可能需要尝试使用 Jupyter 笔记本。不过,您必须在自动完成之前实例化变量。

另一种可能的解决方案是利用 IDE 支持的文件(Python 接口文件存根)。您可以在代码中添加一个小片段,该代码片段使用动态属性实例化类,并记下类接口文件 ()。然后 IDE 将使用它进行自动完成。显然,这个解决方案会有“一次运行延迟”,但就像在 PyCharm 中一样,您只需单击类名附近的星号即可切换到此类文件,您可以在进行大量更改时手动更新它。.pyi.pyi

评论

1赞 red888 2/10/2023
您将如何以编程方式实现此目的?mypy 有 stubgen 工具,但我认为不能导入它并针对这样的动态创建类运行。有没有办法从实例化的类生成一个?writes down a class interfacepyi
0赞 igrinis 2/12/2023
从字面上看,在 __init__() 中创建一个文件并写入您需要的所有内容。.pyi
0赞 nagln 8/27/2020 #2

Spyder 提供自动建议选项而不是自动完成。风筝集成可能有助于更快地设置代码。风筝实际上是一个自动完成插件。还可以将其与 Visual Studio Code 一起使用。

2赞 Yansh 8/29/2020 #3

为此,我不得不使用联合类型来获取所有可能的自动完成选项。编写它需要一些额外的时间,但是当我的程序很大时,这是值得的。

from typing import Union


class dynamic1(object):
    def __init__(self):
        self.b = 5
        self.c = 0


class dynamic2(dynamic1):
    def __init__(self):
        self.e = 10
        self.d = 11


class dynamic3:
    def __init__(self):
        self.f = 12


def func(li):
    return li[1]


def func() -> Union[dynamic1, dynamic2, dynamic3]:
    a = [dynamic1(), dynamic2(), dynamic3()]
    b = func(a)
    return b

Code in action