How do I look inside a Python object?
我开始使用python(包括django web开发和panda3d游戏开发)编写各种项目的代码。
为了帮助我理解正在发生的事情,我想基本上"查看"一下Python对象内部,看看它们是如何工作的,就像它们的方法和属性一样。
假设我有一个python对象,我需要什么来打印它的内容呢?这是可能的吗?
python有一套很强的内省功能。
查看以下内置功能:
type() dir() id() getattr() hasattr() globals() locals() callable()
首先,阅读资料来源。
其次,使用
我很惊讶还没有人提到帮助!
1 2 3 4 5 6 7 8 9 | In [1]: def foo(): ...: "foo!" ...: In [2]: help(foo) Help on function foo in module __main__: foo() foo! |
帮助让您阅读docstring并了解类可能具有哪些属性,这非常有用。
如果这是为了探索,看看到底发生了什么,我建议你看看伊普敦。这会添加各种快捷方式来获取对象文档、属性甚至源代码。例如,附加"?"函数将为对象提供帮助(实际上是"帮助(obj)"的快捷方式,使用两个?s("EDOCX1〔14])将显示源代码(如果可用)。
还有很多额外的便利,比如制表完成、结果的漂亮打印、结果历史等等,这些都使得这种探索性编程非常方便。
为了更具程序性地使用自省功能,基本的内置功能(如
1 2 3 4 5 6 7 8 9 | >>> print inspect.getsource(inspect.getsource) def getsource(object): """Return the text of the source code for an object. The argument may be a module, class, method, function, traceback, frame, or code object. The source code is returned as a single string. An IOError is raised if the source code cannot be retrieved.""" lines, lnum = getsourcelines(object) return string.join(lines, '') |
如果处理包装或操作函数,
如果您对这个图形用户界面感兴趣,请查看objbrowser。它使用python标准库中的inspect模块进行下面的对象内省。
可以在shell中列出dir()对象的属性:
1 2 | >>> dir(object()) ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__'] |
当然,还有inspect模块:http://docs.python.org/library/inspect.html module inspect
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | """Visit http://diveintopython.net/""" __author__ ="Mark Pilgrim ([email protected])" def info(object, spacing=10, collapse=1): """Print methods and doc strings. Takes module, class, list, dictionary, or string.""" methodList = [e for e in dir(object) if callable(getattr(object, e))] processFunc = collapse and (lambda s:"".join(s.split())) or (lambda s: s) print" ".join(["%s %s" % (method.ljust(spacing), processFunc(str(getattr(object, method).__doc__))) for method in methodList]) if __name__ =="__main__": print help.__doc__ |
其他人已经提到了dir()内置的,听起来像是您要找的,但这里还有另一个好提示。许多库(包括大多数标准库)都以源形式分发。这意味着您可以很容易地直接读取源代码。关键在于找到它;例如:
1 2 3 | >>> import string >>> string.__file__ '/usr/lib/python2.5/string.pyc' |
已编译*.py c文件,因此请删除尾随的"c",并在最喜爱的编辑器或文件查看器中打开未编译的*.py文件:
1 | /usr/lib/python2.5/string.py |
我发现这对于发现从给定的API中引发哪些异常非常有用。这种细节在Python世界中很少有很好的文档记录。
试一试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | from ppretty import ppretty class A(object): s = 5 def __init__(self): self._p = 8 @property def foo(self): return range(10) print ppretty(A(), indent=' ', depth=2, width=30, seq_length=6, show_protected=True, show_private=False, show_static=True, show_properties=True, show_address=True) |
输出:
1 2 3 4 5 | __main__.A at 0x1debd68L ( _p = 8, foo = [0, 1, 2, ..., 7, 8, 9], s = 5 ) |
虽然其他人已经提到了
The pprint module provides a capability to"pretty-print" arbitrary
Python data structures in a form which can be used as input to the
interpreter. If the formatted structures include objects which are not
fundamental Python types, the representation may not be loadable. This
may be the case if objects such as files, sockets, classes, or
instances are included, as well as many other built-in objects which
are not representable as Python constants.
具有PHP背景的开发人员可能对
使用
1 2 | from pprint import pprint pprint(vars(your_object)) |
所以,不需要循环。
要转储全局或本地作用域中包含的所有变量,只需使用:
1 2 | pprint(globals()) pprint(locals()) |
1 2 | locals()['foo']() # foo() globals()['foo']() # foo() |
同样,使用
还有更多。
如果您想查看参数和方法,正如其他人指出的那样,您可以使用
如果要查看内容的实际值,可以
有一个python代码库构建就是为了这个目的:在python 2.7中引入了inspect
检查代码的两个重要工具是:
iPython。允许您使用制表符完成检查的python终端。
带有pydev插件的Eclipse。它有一个优秀的调试器,允许您在给定的位置中断,并通过将所有变量浏览为树来检查对象。甚至可以使用嵌入式终端在该位置尝试代码,或者键入对象并按"."让它为您提供代码提示。
PPRINT和DIR一起工作很好
如果您想查看与对象
vars(obj)返回对象的属性。
1 2 3 | import pprint pprint.pprint(obj.__dict__) |
或
1 | pprint.pprint(vars(obj)) |
如果您想查看活动对象的内部,那么python的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | >>> from dill.source import getsource >>> >>> def add(x,y): ... return x+y ... >>> squared = lambda x:x**2 >>> >>> print getsource(add) def add(x,y): return x+y >>> print getsource(squared) squared = lambda x:x**2 >>> >>> class Foo(object): ... def bar(self, x): ... return x*x+x ... >>> f = Foo() >>> >>> print getsource(f.bar) def bar(self, x): return x*x+x >>> |
此外,如果要查看列表和字典,可以使用pprint()。
尝试使用:
1 | print(object.stringify()) |
- 其中,
object 是要检查的对象的变量名。
这将打印出一个格式良好的选项卡式输出,显示对象中键和值的所有层次结构。
注:本品适用于python3。不确定它是否适用于早期版本