【发布时间】:2010-11-03 14:51:10
【问题描述】:
我开始使用 Python 在各种项目中编写代码(包括 Django Web 开发和 Panda3D 游戏开发)。
为了帮助我理解发生了什么,我想基本上“查看” Python 对象内部,看看它们是如何运行的——比如它们的方法和属性。
假设我有一个 Python 对象,我需要打印出它的内容吗?这可能吗?
【问题讨论】:
标签: python introspection
我开始使用 Python 在各种项目中编写代码(包括 Django Web 开发和 Panda3D 游戏开发)。
为了帮助我理解发生了什么,我想基本上“查看” Python 对象内部,看看它们是如何运行的——比如它们的方法和属性。
假设我有一个 Python 对象,我需要打印出它的内容吗?这可能吗?
【问题讨论】:
标签: python introspection
有一个很酷的工具叫做objexplore。这是一个关于如何在 pandas DataFrame 上使用其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)
【讨论】:
vars(obj) 返回对象的属性。
【讨论】:
如果您正在寻找更微妙的解决方案,您可以尝试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
>
>
【讨论】:
在 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"}
【讨论】:
已经有很多好的技巧了,但是最短和最简单的(不一定是最好的)还有待提及:
object?
【讨论】:
尝试使用:
print(object.stringify())
object 是您尝试检查的对象的变量名。这会打印出格式精美的选项卡式输出,显示对象中键和值的所有层次结构。
注意:这适用于 python3。不确定它是否适用于早期版本
更新:这不适用于所有类型的对象。如果您遇到其中一种类型(如 Request 对象),请改用以下类型之一:
dir(object())或
import pprint
然后:
pprint.pprint(object.__dict__)
【讨论】:
如果有兴趣查看对象myobj对应的函数源码,可以输入iPython或Jupyter Notebook:
myobj??
【讨论】:
虽然其他人已经提到了pprint,但我想添加一些上下文。
pprint 模块提供了“漂亮打印”任意 可以用作输入的 Python 数据结构 口译员。如果格式化的结构包含不是 基本的 Python 类型,表示可能无法加载。这 如果对象(例如文件、套接字、类或 包括实例,以及许多其他内置对象 不能表示为 Python 常量。
pprint 可能会受到具有 PHP 背景且正在寻找var_dump() 的替代品的开发人员的高需求。
使用pprint() 与vars() 混合可以很好地转储具有dict 属性的对象,这会返回模块、类、实例等的__dict__ 属性:
from pprint import pprint
pprint(vars(your_object))
要转储 全局 或 本地范围 中包含的所有变量,只需使用:
pprint(globals())
pprint(locals())
locals() 显示在函数中定义的变量。
在other usages 中使用相应名称作为字符串键访问函数也很有用:
locals()['foo']() # foo()
globals()['foo']() # foo()
类似地,使用dir() 查看模块的内容,或对象的属性。
还有更多。
【讨论】:
import pprint
pprint.pprint(obj.__dict__)
或
pprint.pprint(vars(obj))
【讨论】:
pprint.pprint(vars(obj)) 是print(str(obj.__dict__).replace(',',',\n')) 的包装器吗?(合法问题)因为我尝试了这个答案,期望得到比print(str(obj.__dict__).replace(',','\n')) 得到的更多信息
【讨论】:
检查代码的两个很棒的工具是:
IPython。一个 python 终端,允许您使用制表符完成进行检查。
Eclipse 与 PyDev plugin。它有一个出色的调试器,允许您在给定的位置中断并通过将所有变量作为树浏览来检查对象。您甚至可以使用嵌入式终端在该位置尝试代码或键入对象并按“。”让它为您提供代码提示。
【讨论】:
试试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
)
【讨论】:
"""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__
【讨论】:
如果您对此 GUI 感兴趣,请查看objbrowser。它使用 Python 标准库中的检查模块进行底层对象自省。
【讨论】:
有一个专门为此目的构建的 python 代码库:inspect 在 Python 2.7 中引入
【讨论】:
如果您想查看活动对象内部,那么 python 的 inspect 模块是一个很好的答案。通常,它用于获取在磁盘上某个源文件中定义的函数的源代码。如果您想获取解释器中定义的实时函数和 lambda 的源代码,您可以使用 dill 中的 dill.source.getsource。它还可以从 curries 中定义的绑定或未绑定的类方法和函数中获取代码……但是,如果没有封闭对象的代码,您可能无法编译该代码。
>>> 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
>>>
【讨论】:
我很惊讶还没有人提到帮助!
In [1]: def foo():
...: "foo!"
...:
In [2]: help(foo)
Help on function foo in module __main__:
foo()
foo!
帮助让您阅读文档字符串并了解类可能具有的属性,这非常有帮助。
【讨论】:
其他人已经提到了 dir() 内置,这听起来像您正在寻找的,但这里有另一个很好的提示。许多库——包括大多数标准库——都以源代码形式分发。这意味着您可以很容易地直接阅读源代码。诀窍在于找到它。例如:
>>> import string
>>> string.__file__
'/usr/lib/python2.5/string.pyc'
*.pyc 文件已编译,因此删除尾随的“c”并在您喜欢的编辑器或文件查看器中打开未编译的 *.py 文件:
/usr/lib/python2.5/string.py
我发现这对于发现诸如从给定 API 引发的异常之类的事情非常有用。这种细节在 Python 世界中很少有详细记录。
【讨论】:
如果这是为了探索以了解发生了什么,我建议查看IPython。这添加了各种快捷方式来获取对象文档、属性甚至源代码。例如附加一个“?”到函数将为对象提供帮助(实际上是“帮助(obj)”的快捷方式,而使用两个?(“func??”)将显示源代码(如果可用)。
还有很多额外的便利,比如制表符补全、漂亮的结果打印、结果历史记录等,这使得这种探索性编程非常方便。
对于内省的更多程序化使用,dir()、vars()、getattr 等基本内置函数将很有用,但值得您花时间查看 inspect 模块。要获取函数的来源,请使用“inspect.getsource”,例如,将其应用于自身:
>>> 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__
【讨论】:
vars(object) 就是为此而生的。
from pprint import pprint; pprint(vars(object)) 让我对我的对象的内容有了一个非常好的看法。谢谢@liberforce
如果您想查看参数和方法,正如其他人指出的那样,您可以使用pprint 或dir()
如果要查看内容的实际值,可以这样做
object.__dict__
【讨论】:
pprint 和 dir 一起工作很棒
【讨论】:
此外,如果你想查看列表和字典,你可以使用 pprint()
【讨论】:
你可以在 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
【讨论】:
首先,阅读源代码。
其次,使用dir()函数。
【讨论】: