0

有谁知道 pydev 如何确定用于代码完成的内容?我正在尝试定义一组专门用于启用代码完成的类。我尝试使用__new__to set__dict__和 also __slots__,但似乎都没有在 pydev 自动完成中列出。

我有一组要在自动完成中列出的枚举,但我想将它们设置在生成器中,而不是为每个类都硬编码。

所以而不是

class TypeA(object):
    ValOk = 1
    ValSomethingSpecificToThisClassWentWrong = 4
    def __call__(self):
        return 42

我想做类似的事情

def TYPE_GEN(name, val, enums={}):
    def call(self):
        return val
    dct = {}
    dct["__call__"] = call
    dct['__slots__'] = enums.keys()
    for k, v in enums.items():
        dct[k] = v
    return type(name, (), dct)

TypeA = TYPE_GEN("TypeA",42,{"ValOk":1,"ValSomethingSpecificToThisClassWentWrong":4})

我能做些什么来帮助处理?

编辑: 评论似乎是在质疑我在做什么。同样,我所追求的很大一部分是代码完成。我正在使用 python 绑定到协议来与各种微控制器通信。我可以更改的每个参数(有数百个)在概念上都有一个名称,但在协议上我需要使用它的 ID,这实际上是随机的。许多参数接受在概念上命名但又由整数表示的值。因此枚举。

我正在尝试为该库自动生成一个 python 模块,因此该组可以使用名称而不是容易出错的数字来指定他们想要更改的内容。该__call__属性将返回参数的 id,枚举是参数的允许值。

是的,我可以生成每个类的详细版本。每种类型的一行对我来说似乎更清楚,因为重点是自动完成,而不是查看这些类。

4

3 回答 3

1

好的,正如所指出的,您的代码太动态了... PyDev 只会静态分析您自己的代码(即:存在于您项目中的代码)。

尽管如此,还是有一些选择:

选项1:

您可以强制 PyDev 动态分析库中的代码(即:站点包中),在这种情况下,它可以通过 shell 动态获取该信息。

为此,您必须在站点包和解释器配置中创建一个模块,您需要将其添加到“强制内置”中。有关详细信息,请参见:http ://pydev.org/manual_101_interpreter.html 。

选项 2:

另一种选择是将它放入您的预定义完成中(但在这种情况下,它还需要在解释器配置中,而不是在您的代码中 - 无论如何您都必须在此处明确完成)。请参阅上面的链接以了解如何执行此操作。

选项 3:

生成实际代码。我相信 Cog ( http://nedbatchelder.com/code/cog/ ) 是最好的选择,因为您可以编写 python 代码来输出文件的内容,然后您可以更改代码/重新运行 cog 以更新内容需要(如果您想要正确完成而不需要将代码作为 PyDev 中的库,我相信这将是最好的选择——并且您将能够更好地掌握您所拥有的内容,因为您的结构将是明确的那里)。

请注意,如果您使用其他语言(例如 Java/C++ 等),则 cog 也可以使用。因此,无论此特定问题如何,我都建议您将其添加到您的工具集中。

于 2013-08-15T17:24:04.927 回答
0

在“离线”编辑器中(而不是在交互式 Python shell 中),Python 的完全通用代码完成实际上是不可能的。

原因是 Python 太动态了;基本上任何事情都可以随时改变。如果我键入TypeA.Val并要求完成,系统必须知道TypeA绑定到什么对象,它的类是什么,以及两者的属性是什么。所有这三个事实都可以改变(并且做;TypeA开始未定义并且仅在程序执行期间的某个特定点绑定到对象)。

因此,系统必须知道您希望从程序运行的哪个点完成?即使有一些明确的方式来指定它,也没有一般的方法可以知道程序中所有内容的状态,而无需实际运行到该点,您可能不希望您的编辑器这样做!

所以 pydev 所做的是猜测,当它很明显时。foo如果您在定义类的模块中有一个类块Bar,那么可以肯定的是,Bar导入的名称foo将引用该类。因此,您知道在 . 下Bar.或在由obj = Bar(). 当然,程序可以在运行时重新绑定foo.Bar(或更改其属性集),或者可以在import foo遇到其他文件的环境中运行。但是这种事情很少发生,并且完成在常见情况下很有用。

但这意味着,只要您“过多”地使用 Python 的动态语言灵活性,您基本上就会失去完成。通过调用函数来定义类就是其中一种情况。它还没有准备好猜测TypeA有名称ValOkValSomethingSpecificToThisClassWentWrong; 毕竟,调用 to 可能会产生许多其他对象TYPE_GEN,但它们都有不同的名称。

因此,如果您的主要目标是完成,我认为您必须简化 pydev 并完整地编写这些类。当然,如果需要,您可以使用类似的代码(以文本方式)生成 python 文件。不过,看起来用字典定义这些实际上比作为一个类有更多的“语法开销”;您正在"a": b,按项目而不是a = b. 除非您可以更系统地生成这些或解析现有的定义文件或其他东西,否则我认为我会发现静态类定义比字典驱动容易读写TYPE_GEN

于 2013-08-12T22:47:35.113 回答
0

您的代码越简单,完成工作的可能性就越大。将其作为一个单独的工具来生成包含上述类定义的 Python 代码文件是否合理?这基本上是两全其美的。您甚至可以将名称/值对放在 JSON 或 INI 文件或您拥有的文件中,从而消除名称/值对中方法调用的混乱。唯一的缺点是需要在代码更改时运行该工具来重新生成代码文件,但至少这是一个自动化、简单的过程。

就个人而言,我只会让事情变得更冗长并手动写出类,但这只是我的意见。

在旁注中,我认为使类可调用与仅具有id类变量相比没有多大好处。两者都需要知道输入什么:TypeA()vs TypeA.id. 如果你想防止实例化,我认为抛出异常__init__会更清楚你的意图。

于 2013-08-12T20:20:51.207 回答