如何查看Python对象内部?

我开始使用Python编写各种项目的代码(包括Django web开发和Panda3D游戏开发)。

为了帮助我理解发生了什么,我想基本上“看看”Python对象内部,看看它们是如何运行的——比如它们的方法和属性。

假设我有一个Python对象,我需要什么来打印它的内容?这可能吗?

429772 次浏览

首先,阅读原文。

其次,使用dir()函数。

你可以在shell中使用dir()列出对象的属性:

>>> 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

"""Visit http://diveintopython.net/"""


__author__ = "Mark Pilgrim (mark@diveintopython.org)"




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 "\n".join(["%s %s" %
(method.ljust(spacing),
processFunc(str(getattr(object, method).__doc__)))
for method in methodList])


if __name__ == "__main__":
print help.__doc__

Python有一组强大的自省特性。

看一下下面的内置函数:

type()dir()分别在检查对象的类型及其属性集时特别有用。

此外,如果您想查看列表和字典内部,可以使用pprint()

Pprint和dir一起工作效果很好

如果你想查看参数和方法,就像其他人指出的那样,你可以使用pprintdir()

如果您想查看内容的实际值,可以这样做

object.__dict__

如果这是为了探究发生了什么,我建议查看IPython。这增加了获取对象文档、属性甚至源代码的各种快捷方式。例如,在函数后附加一个"?"将为对象提供帮助(有效地为"help(obj)"提供快捷方式),而使用两个"?" ("func??")将在可用时显示源代码。

还有很多额外的便利,如制表符补全、结果打印、结果历史记录等,这对于这种探索性编程非常方便。

对于更多的自省的编程使用,基本的内置程序,如dir()vars()getattr等将是有用的,但值得你花时间检查检查模块。要获取函数的源,使用"inspect.getsource" eg,将其应用于自身:

>>> 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, '')

inspect.getargspec在处理包装或操作函数时也经常有用,因为它会给出函数形参的名称和默认值。

object.__dict__

其他人已经提到了dir()内置,这听起来像是您正在寻找的,但这里有另一个很好的提示。许多库——包括大多数标准库——都是以源代码形式发布的。这意味着您可以很容易地直接阅读源代码。诀窍在于找到它;例如:

>>> import string
>>> string.__file__
'/usr/lib/python2.5/string.pyc'

*。Pyc文件已编译,因此删除后面的'c',并在您最喜欢的编辑器或文件查看器中打开未编译的*.py文件:

/usr/lib/python2.5/string.py

我发现这对于发现从给定API引发哪些异常等事情非常有用。这种细节在Python世界中很少有良好的文档。

我很惊讶居然没人提到帮助!

In [1]: def foo():
...:     "foo!"
...:


In [2]: help(foo)
Help on function foo in module __main__:


foo()
foo!

Help让您阅读文档字符串并了解类可能具有的属性,这非常有用。

如果你想查看活动对象的内部,那么python的inspect模块是一个很好的答案。一般来说,它适用于获取磁盘上某个源文件中定义的函数的源代码。如果你想获得解释器中定义的活动函数和lambda的源代码,你可以从dill中使用dill.source.getsource。它还可以从在curry中定义的绑定或未绑定类方法和函数中获取代码…但是,如果没有封闭对象的代码,则可能无法编译该代码。

>>> 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


>>>

有一个python代码库构建就是为了这个目的:检查在python 2.7中引入

如果你对此感兴趣,可以看一下objbrowser。它使用Python标准库中的inspect模块进行下面的对象内省。

 objbrowser截图

尝试ppretty

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)

输出:

__main__.A at 0x1debd68L (
_p = 8,
foo = [0, 1, 2, ..., 7, 8, 9],
s = 5
)

检查代码的两个好工具是:

  1. IPython。一个允许你使用制表符完成检查的python终端。

  2. EclipsePyDev插件。它有一个优秀的调试器,允许您在给定的位置中断,并通过浏览所有变量作为树来检查对象。您甚至可以使用嵌入式终端在该位置尝试编码或键入对象并按'。,让它为你提供代码提示。

enter image description here

vars(obj)返回对象的属性。

import pprint


pprint.pprint(obj.__dict__)

pprint.pprint(vars(obj))

虽然pprint已经被其他人提到了,但我想添加一些上下文。

pprint模块提供了“漂亮打印”的能力 形式的Python数据结构,该形式可用作 翻译。如果格式化的结构包含的对象不是 基本的Python类型,表示可能是不可加载的。这 如果对象,如文件,套接字,类,或 实例包括在内,以及许多其他内置对象 不能表示为Python常量。

有PHP背景的开发人员正在寻找var_dump()的替代品,他们可能非常需要pprint

具有dict属性的对象可以很好地使用pprint()vars()进行转储,后者返回模块、类、实例等的__dict__属性:

from pprint import pprint
pprint(vars(your_object))

所以,不需要循环

要转储全球局部作用域中包含的所有变量,只需使用:

pprint(globals())
pprint(locals())

locals()显示函数中定义的变量 在其他用法:

之间以字符串键访问对应名称的函数也很有用
locals()['foo']() # foo()
globals()['foo']() # foo()

类似地,使用dir()来查看模块的内容或对象的属性。

还有更多。

尝试使用:

print(object.stringify())
  • 其中object是你要检查的对象的变量名。

这将打印出格式化良好的选项卡输出,显示对象中所有键和值的层次结构。

注意:这在python3中有效。不确定它是否适用于早期版本

更新:这并不适用于所有类型的对象。如果你遇到了这些类型之一(比如Request对象),请使用以下类型之一:

  • dir(object())

< p > import pprint 然后: pprint.pprint(object.__dict__) < / p >

如果你有兴趣查看对象myobj对应的函数的源代码,你可以输入iPythonJupyter Notebook:

myobj??

已经有很多好的提示了,但还没有提到最短和最简单的(不一定是最好的):

object?

在Python 3.8中,可以使用__dict__来打印对象的内容。例如,

class Person():
pass


person = Person()


## set attributes
person.first = 'Oyinda'
person.last = 'David'


## to see the content of the object
print(person.__dict__)


{"first": "Oyinda", "last": "David"}

如果你正在寻找一个稍微更微妙的解决方案,你可以尝试objprint。它的一个积极的方面是它可以处理嵌套对象。例如:

from objprint import objprint


class Position:
def __init__(self, x, y):
self.x = x
self.y = y


class Player:
def __init__(self):
self.name = "Alice"
self.age = 18
self.items = ["axe", "armor"]
self.coins = {"gold": 1, "silver": 33, "bronze": 57}
self.position = Position(3, 5)


objprint(Player())

会打印出来

<Player
.name = 'Alice',
.age = 18,
.items = ['axe', 'armor'],
.coins = {'gold': 1, 'silver': 33, 'bronze': 57},
.position = <Position
.x = 3,
.y = 5
>
>

有一个非常酷的工具叫做objexplore。下面是一个简单的例子,说明如何在pandas数据框架上使用explore函数。

import pandas as pd
df=pd.read_csv('https://storage.googleapis.com/download.tensorflow.org/data/heart.csv')


from objexplore import explore
explore(df)
将在你的shell中弹出以下内容: enter image description here < / p >