简单方法调查未知的Python API
在研究一段不太熟悉的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 个回答
我会采取一种互动的方法,类似于Lie Ryan的做法:在调试模式下运行脚本,在你感兴趣的那一行设置一个断点,然后可以实时查询你想要的变量。
这种方法比你提到的“扫描源代码寻找匹配的方法名”要更可靠,因为它能确保你得到的就是你真正想了解的那个变量,而不是一堆可能的选项。
我有时候会在我的代码里插入 help(varName)
,这样当运行到这个特定的函数时,就会显示帮助文件。例如,如果我有以下这段代码:
def foo(bar):
bar.baz()
如果我想弄清楚 bar 是什么类型,以及 .baz 是干嘛的,我只需要插入这个
def foo(bar):
help(bar)
help(bar.baz)
bar.baz()
然后运行脚本。还有一种不那么干扰的方法是使用 print type(bar)
。
你需要使用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
可以获得更多详细信息)。