有谁知道pydev如何确定代码完成的用途?我正在尝试定义一组专门用于启用代码完成的类。我尝试使用__new__
设置__dict__
和__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,枚举是参数的允许值。
是的,我可以生成每个类的详细版本。每种类型的一行对我来说似乎更清晰,因为这一点是自动完成的,而不是查看这些类。
答案 0 :(得分:1)
好的,正如所指出的那样,你的代码太动态了...... PyDev只会静态地分析你自己的代码(即:代码存在于你的项目中)。
仍有一些替代方案:
选项1:
您可以强制PyDev动态分析库中的代码(即:在site-packages中),在这种情况下,它可以通过shell动态获取该信息。
要做到这一点,你必须在site-packages中创建一个模块,在你的解释器配置中,你需要将它添加到'forced builtins'中。有关详细信息,请参阅:http://pydev.org/manual_101_interpreter.html。
选项2:
另一种选择是将它放入预定义的完成中(但在这种情况下,它也需要在解释器配置中,而不是在你的代码中 - 并且你必须在那里使得完成显式)。请参阅上面的链接,了解如何执行此操作。
选项3:
生成实际代码。我相信Cog(http://nedbatchelder.com/code/cog/)是最好的选择,因为你可以编写python代码来输出文件的内容,你可以稍后更改代码/重新运行cog来更新所需的内容(如果你想要正确的完成)我不需要把你的代码放在PyDev的库中,我相信这是最好的替代方案 - 而且你能够更好地掌握你所拥有的东西,因为你的结构在那里是明确的。)
请注意,如果您使用其他语言(例如Java / C ++等),cog也会起作用。因此,无论此特定问题如何,我都建议您将其添加到工具集中。
答案 1 :(得分:0)
代码越简单,完成工作的可能性就越大。将此作为一个单独的工具来生成包含上述类定义的Python代码文件是否合理?这基本上是两个世界中最好的。您甚至可以将名称/值对放在JSON或INI文件中或者有什么用途,从而消除了名称/值对中方法调用的混乱。唯一的缺点是需要运行工具来在代码更改时重新生成代码文件,但至少这是一个自动化,简单的过程。
就个人而言,我只是想让事情更加冗长并手动写出类,但这只是我的意见。
另一方面,我认为使类可调用而不仅仅是拥有id
类变量并没有多大好处。两者都需要知道输入内容:TypeA()
vs TypeA.id
。如果你想阻止实例化,我认为在__init__
中抛出一个例外会更清楚你的意图。
答案 2 :(得分:0)
在“离线”编辑器中实际上不能实现Python的完全通用代码完成(而不是在交互式Python shell中)。
原因是Python过于动态;基本上任何事情都可以随时改变。如果我输入TypeA.Val
并要求完成,系统必须知道绑定的对象TypeA
,类的类型以及两者的属性是什么。所有这3个事实都可以改变(并且可以;并且TypeA
开始未定义,并且仅在程序执行期间的某个特定点绑定到对象。)
因此,系统必须知道程序运行中的哪个点你想要完成?即使有一些明确的方式来指定它,也没有一般的方法来知道程序中的所有内容的状态是什么样的,而不是实际运行到那一点,你可能不希望你的编辑器做!
所以pydev做的是猜测,当它非常明显时。如果您在定义类foo
的模块Bar
中有一个类块,那么可以肯定的是,从Bar
导入的名称foo
将引用该类。因此,您可以了解Bar.
下可以访问的名称,或obj = Bar()
创建的对象。当然,程序可以在运行时重新绑定foo.Bar
(或改变其属性集),或者可以在import foo
正在访问其他文件的环境中运行。但是这种事情很少发生,并且完成在常见情况下很有用。
这意味着,无论何时使用Python的动态语言灵活性“过多”,您基本上都会失败。通过调用函数来定义类是其中一种情况。我们还没有准备好猜测TypeA
名称为ValOk
和ValSomethingSpecificToThisClassWentWrong
;毕竟,调用TYPE_GEN
可能会产生许多其他对象,但它们都有不同的名称。
因此,如果你的主要目标是完成,我认为你必须让pydev变得容易,并完整地编写这些类。当然,如果需要,可以使用类似的代码生成python文件(文本)。看起来虽然实际上有更多的“句法开销”用词典来定义它们而不是作为一个类;你是按照每个项目编写"a": b,
而不是a = b
。除非您可以更系统地生成这些文件或解析现有的定义文件或其他内容,否则我认为静态类定义比驱动TYPE_GEN
的字典更容易阅读和。