简单方法调查未知的Python API

3 投票
6 回答
986 浏览
提问于 2025-04-15 23:57

在研究一段不太熟悉的Python代码时,我有时会遇到这样的情况:

varName.methodName()

为了弄清楚这是什么,我需要更深入地研究代码,找出varName是在哪里被创建的,看看它的类型。如果varName确实是ClassName这个类的一个实例,那我就知道methodName()ClassName类的方法。

有时候,varName可能等于self,这时methodName()就是当前类的方法,或者是从其他类继承过来的方法,如果当前类是从其他类派生出来的。

有没有什么快速的方法或工具,可以输入'methodName',然后扫描所有安装的Python模块,显示哪些类有methodName()这个方法呢?

我知道的最接近的工具是ipython。如果我输入一个类名,然后加个点('.'),再按TAB键,它就能显示这个类的成员。其实我也可以用一个对象的名字(这个对象是某个类的实例),这样也能工作。一旦我从提供的选项中选择了一个方法名,我可以输入'?'或'??'来获取帮助,如果有文档字符串的话。

我在想,ipython是否能仅仅根据'methodName'这个字符串进行智能扫描。

如果你知道其他可以帮助实现这个功能的工具,请告诉我。

补充说明:应要求,我特别想要一种方法,可以通过方法名查找方法,不仅仅在Python源代码文件中。有些Python包(特别是PyQt)包含很多.so文件,而ipython能够通过先导入它们来完成补全。所以像grep(甚至ctags)这样的纯文本搜索在这里是行不通的。

6 个回答

1

我会采取一种互动的方法,类似于Lie Ryan的做法:在调试模式下运行脚本,在你感兴趣的那一行设置一个断点,然后可以实时查询你想要的变量。

这种方法比你提到的“扫描源代码寻找匹配的方法名”要更可靠,因为它能确保你得到的就是你真正想了解的那个变量,而不是一堆可能的选项。

3

我有时候会在我的代码里插入 help(varName),这样当运行到这个特定的函数时,就会显示帮助文件。例如,如果我有以下这段代码:

def foo(bar):
    bar.baz()

如果我想弄清楚 bar 是什么类型,以及 .baz 是干嘛的,我只需要插入这个

def foo(bar):
    help(bar)
    help(bar.baz)
    bar.baz()

然后运行脚本。还有一种不那么干扰的方法是使用 print type(bar)

3

你需要使用Exuberant ctags(旧版的ctags无法为Python生成标签)。

安装完成后(安装方法取决于你的操作系统),你可以在你的文件上运行它:

$ /usr/local/bin/ctags *py

(你可以多次运行它来将标签添加到已有的标签文件中,也可以让它递归进入子目录等等,所有这些都可以通过命令行选项来实现),它会生成一个像下面这样的tags文件(为了简洁起见,我这里用一个包含一个类和一个方法的单个Python文件):

$ cat tags
!_TAG_FILE_FORMAT   2   /extended format; --format=1 will not append ;" to lines/
!_TAG_FILE_SORTED   1   /0=unsorted, 1=sorted, 2=foldcase/
!_TAG_PROGRAM_AUTHOR    Darren Hiebert  /dhiebert@users.sourceforge.net/
!_TAG_PROGRAM_NAME  Exuberant Ctags //
!_TAG_PROGRAM_URL   http://ctags.sourceforge.net    /official site/
!_TAG_PROGRAM_VERSION   5.7 //
Foo a.py    /^class Foo(object):$/;"    c
amethod a.py    /^  def amethod(self): pass$/;" m   class:Foo

现在,引用这篇文章

假设你发现了一个函数调用,想查看它的定义,只需将光标移动到那个函数上,然后按下ctrl ],就会跳转到定义那里。如果你想返回到之前的位置,只需按ctrl t。除了ctrl t,我更喜欢使用ctrl i和ctrl o来在检查点之间前后移动。

另外,按下control-P可以对在tags中找到的标识符进行(某种尝试的)代码补全。(在vim中输入:help tags可以获得更多详细信息)。

撰写回答