用于返回python对象方法的Intellisense

时间:2016-01-23 11:40:42

标签: python intellisense static-analysis tooling

我是Python的新手,我非常喜欢这门语言。但是我最近在eclipse中使用PyDev时遇到了一个恼人的问题。

某些方法返回某个类的实例。但我无法获得实例方法的智能感知。

例如:

import openpyxl
from openpyxl.reader.excel import load_workbook
from openpyxl.worksheet import Worksheet


xlsFile='hello.xlsx'
wbook = load_workbook(xlsFile)

wsheet1=wbook.get_sheet_by_name('mysheet')
wsheet1.cell('A9').hyperlink=r'\\sharefolder'

wsheet2=Worksheet()
wsheet2.cell('A1').hyperlink=r'\\sharefolder'

在此代码中,我可以使用cell()获取方法wsheet2的提示,但不能使用wsheet1。虽然它们都是我已导入的Worksheet类型。似乎python或PyDev无法正确检测返回对象的类型。

这是语言限制吗?或者我做错了什么?现在,我必须深入研究源代码,看看返回值的实际类型是什么。然后检查该类型中定义的方法。这很乏味。

我写了一个小测试来重现这个问题。奇怪的是,intellisense看起来很有效。

enter image description here

2 个答案:

答案 0 :(得分:2)

这是Python动态输入的结果。

在诸如C#的静态类型语言中,方法是带有类型签名的注释。 (旁白:在某些系统类型中,类型检查器可以推断。)编译器知道函数的返回类型,以及参数的类型,而不运行代码,因为你写下类型!这使您的工具不仅可以检查程序的类型,还可以构建有关程序中方法及其类型的元数据; Intellisense通过查询从程序文本中获取的元数据来工作。

Python没有内置于该语言的静态类型系统。这使得工具更难以在不运行代码的情况下为您提供提示。例如,这个函数的返回类型是什么?

def spam(eggs):
    if eggs:
        return "ham"
    return 42

有时spam会返回一个字符串;有时它会返回一个整数。 Intellisense应该在调用spam的返回值时显示哪些方法?

这个课程有哪些可用的属性?

class Spam:
    def __getattr__(self, name):
        if len(name) > 5:
            return "foo"
        return super().__getattr__(name)

Spam有时会动态生成属性:Intellisense应为Spam的实例显示什么?

在这些情况下没有正确答案。您可以自愿进行一些猜测(例如,您可以在str的返回值上显示包含intspam方法的列表,但是您不能提出一直适当的建议。

因此,Python的Intellisense工具减少到最佳猜测。在您给出的示例中,您的IDE对get_sheet_by_name的返回类型了解不足,无法为您提供有关wsheet1的信息。但是,它确实知道wsheet2的类型,因为您只是将其实例化为Worksheet。在你的第二个例子中,Intellisense只是通过检查其源代码来对f1的返回类型进行(正确)猜测。

顺便说一下,像IPython这样的交互式shell中的自动完成更可靠。这是因为IPython实际上运行您键入的代码。它可以告诉对象的运行时类型是什么,因为分析是在运行时发生的。

答案 1 :(得分:1)

嗯,从技术上来说,Python中的方法可以返回任何内容,只有在操作完成时才定义操作的结果。

考虑这个简单的功能:

def f(a):
    if a == 1:
        return 1 # returns int
    elif a == 2:
        return "2" # returns string
    else:
        return object() # returns an `object` instance

该函数对Python非常有效,其结果是严格定义的,但只有在函数执行的最后。事实上:

>>> type(f(1))
<type 'int'>
>>> type(f(2))
<type 'str'>
>>> type(f(3))
<type 'object'>

当然,这种灵活性并不是一直需要的,而且大多数方法都会返回可预测的先决条件。智能IDE可以分析代码(以及一些其他提示,例如可以指定参数和返回类型的文档字符串),但这总是可以用一定的置信度来猜测。还有PEP0484在语言级别引入了类型提示,但它是可选的,相对较新,所有遗留代码肯定不会使用它。

如果PyDev不能用于某个特定情况,那么很遗憾,但是如果选择像Python这样的动态语言,那么你应该接受它。也许值得尝试一个不同的,更智能的IDE,或者在IDE旁边打开一个带有交互式Python提示的控制台,以便动态测试您的代码。我建议使用像bpython

这样复杂的python shell