这样我就可以通过查看对象的状态来调试我的脚本。
您希望将vars()
与pprint()
混合使用:
from pprint import pprint
pprint(vars(your_object))
vars()
简单地返回其参数的 __dict__
,并且在没有 __dir__
方法的情况下,它也是 dir()
的后备。因此,首先使用 dir()
,就像我之前说的一样。 - user3850dir()
函数会返回所有内置的东西,像__str__
和__new__
这些你可能不太关心的。而vars()
函数则不会包含它们。 - Timmmm__dict__
属性的集合和其他对象,此方法会失败。 - anatoly techtonik你把两件不同的事情混在一起了。
使用 dir()
、vars()
或 inspect
模块来获取你感兴趣的内容(我以 __builtins__
为例;你可以使用任何对象)。
>>> l = dir(__builtins__)
>>> d = __builtins__.__dict__
以任何你喜欢的方式打印那个字典:
>>> print l
['ArithmeticError', 'AssertionError', 'AttributeError',...
或者>>> from pprint import pprint
>>> pprint(l)
['ArithmeticError',
'AssertionError',
'AttributeError',
'BaseException',
'DeprecationWarning',
...
>>> pprint(d, indent=2)
{ 'ArithmeticError': <type 'exceptions.ArithmeticError'>,
'AssertionError': <type 'exceptions.AssertionError'>,
'AttributeError': <type 'exceptions.AttributeError'>,
...
'_': [ 'ArithmeticError',
'AssertionError',
'AttributeError',
'BaseException',
'DeprecationWarning',
...
在交互式调试器中,也可以使用命令进行漂亮的打印:
(Pdb) pp vars()
{'__builtins__': {'ArithmeticError': <type 'exceptions.ArithmeticError'>,
'AssertionError': <type 'exceptions.AssertionError'>,
'AttributeError': <type 'exceptions.AttributeError'>,
'BaseException': <type 'exceptions.BaseException'>,
'BufferError': <type 'exceptions.BufferError'>,
...
'zip': <built-in function zip>},
'__file__': 'pass.py',
'__name__': '__main__'}
__dict__
成员(例如re.MatchObject
),但内置的dir()
函数适用于所有对象。 - hobsprint re.compile(r'slots').search('No slots here either.').__slots__
- hobsinspect
模块呢?我认为它是最接近 print_r 或 var_dump 的模块。 - Hai Phaikawldir()
列出的属性背后的值呢?dir()
仅返回名称列表,并非所有这些名称都存在于vars()
或__dict__
属性中。 - HelloGoodbyedef dump(obj):
for attr in dir(obj):
print("obj.%s = %r" % (attr, getattr(obj, attr)))
市面上有许多第三方函数可添加诸如异常处理、特殊字符打印、递归嵌套对象等功能,这些功能按照其作者的偏好实现。但实际上,它们都可以归结为以下基本内容。
inspect
模块中的 getmembers()
函数,但我认为这个方法更有用,因为它演示了如何进行反射。 - Dan Lenski__dict__
中找不到(例如 __doc__
和 __module__
)。此外,对于使用 __slots__
声明的对象,__dict__
根本不起作用。一般来说,__dict__
显示实际上存储在内部字典中的用户级属性。而 dir() 显示更多信息。 - Dan Lenski__dict__
属性/成员。我知道这很疯狂,但它是真实的。像int
和str
或re.MatchObject
这样的内置对象是常见例子。尝试一下 'hello'.__dict__
,然后再尝试一下 dir('hello')
。 - hobsdir
已经提到过了,但它只会给出属性的名称。如果您还想获取它们的值,请尝试使用__dict__
。
class O:
def __init__ (self):
self.value = 3
o = O()
以下是输出结果:
>>> o.__dict__
{'value': 3}
set
这样的对象没有 __dict__
属性,所以对它们使用 __dict__
会抛出 AttributeError: 'set' object has no attribute '__dict__'
错误。 - anatoly techtonik有没有内置的函数可以打印出一个对象的所有当前属性和值?
没有。最受欢迎的答案排除了某些类型的属性,而被接受的答案则显示如何获取所有属性,包括方法和非公共API的部分。但是没有很好的完整的内置函数可以做到这一点。
所以简短的推论是你可以自己编写一个函数,但它会计算属性和其他计算的数据描述符,这些都是公共API的一部分,而你可能不希望这样做:
from pprint import pprint
from inspect import getmembers
from types import FunctionType
def attributes(obj):
disallowed_names = {
name for name, value in getmembers(type(obj))
if isinstance(value, FunctionType)}
return {
name: getattr(obj, name) for name in dir(obj)
if name[0] != '_' and name not in disallowed_names and hasattr(obj, name)}
def print_attributes(obj):
pprint(attributes(obj))
观察当前得票最高的回答在一个包含许多不同类型数据成员的类上的应用:
from pprint import pprint
class Obj:
__slots__ = 'foo', 'bar', '__dict__'
def __init__(self, baz):
self.foo = ''
self.bar = 0
self.baz = baz
@property
def quux(self):
return self.foo * self.bar
obj = Obj('baz')
pprint(vars(obj))
仅打印:
{'baz': 'baz'}
由于 vars 仅返回对象的
__dict__ ,并且它不是副本,因此如果您修改由vars返回的字典,则还会修改对象本身的
__dict__ 。
<code><code><code>vars(obj)['quux'] = 'WHAT?!'
vars(obj)
</code></code></code>
返回:
{'baz': 'baz', 'quux': 'WHAT?!'}
--这很糟糕,因为quux是一个我们不应该设置且不应该在命名空间中的属性... 应用当前被接受的答案(和其他答案)的建议并不好。
>>> dir(obj)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'bar', 'baz', 'foo', 'quux']
正如我们所看到的,dir
只返回与对象相关联的所有名称(实际上只是大部分)。
在评论中提到的 inspect.getmembers
同样存在缺陷 —— 它会返回所有名称和值。
来自类
在教学时,我让我的学生创建一个函数,提供对象的语义公共 API:
def api(obj):
return [name for name in dir(obj) if name[0] != '_']
我们可以扩展这个方法,提供一个对象的语义命名空间的拷贝,但是我们需要排除未分配的__slots__
,如果我们认真考虑“当前属性”的请求,我们需要排除计算属性(因为它们可能会变得很昂贵,而且可能被解释为不是“当前的”):
from types import FunctionType
from inspect import getmembers
def attrs(obj):
disallowed_properties = {
name for name, value in getmembers(type(obj))
if isinstance(value, (property, FunctionType))
}
return {
name: getattr(obj, name) for name in api(obj)
if name not in disallowed_properties and hasattr(obj, name)
}
现在我们不计算或显示属性quux:
>>> attrs(obj)
{'bar': 0, 'baz': 'baz', 'foo': ''}
注意事项
也许我们确实知道我们的属性不贵。我们可能想要更改逻辑以包含它们。或者,我们想排除其他自定义数据描述符。
那么我们需要进一步自定义此函数。因此,具有魔力,完全知道我们想要的并提供它的内置函数是没有意义的。这是我们需要自己创建的功能。
结论
没有现成的函数可以做到这一点,您应该根据您的情况选择最语义化的方法。
from collections import * ; obj=Counter([3,4])
。 - Smart Manoj>>> import sys
>>> dir(sys)
['__displayhook__', '__doc__', '__excepthook__', '__name__', '__stderr__', '__stdin__', '__stdo
t__', '_current_frames', '_getframe', 'api_version', 'argv', 'builtin_module_names', 'byteorder
, 'call_tracing', 'callstats', 'copyright', 'displayhook', 'dllhandle', 'exc_clear', 'exc_info'
'exc_type', 'excepthook', 'exec_prefix', 'executable', 'exit', 'getcheckinterval', 'getdefault
ncoding', 'getfilesystemencoding', 'getrecursionlimit', 'getrefcount', 'getwindowsversion', 'he
version', 'maxint', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks', 'path_importer_
ache', 'platform', 'prefix', 'ps1', 'ps2', 'setcheckinterval', 'setprofile', 'setrecursionlimit
, 'settrace', 'stderr', 'stdin', 'stdout', 'subversion', 'version', 'version_info', 'warnoption
', 'winver']
>>>
另一个有用的功能是帮助。
>>> help(sys)
Help on built-in module sys:
NAME
sys
FILE
(built-in)
MODULE DOCS
http://www.python.org/doc/current/lib/module-sys.html
DESCRIPTION
This module provides access to some objects used or maintained by the
interpreter and to functions that interact strongly with the interpreter.
Dynamic objects:
argv -- command line arguments; argv[0] is the script pathname if known
为打印出对象的当前状态,您可以执行以下操作:
>>> obj # in an interpreter
或者print repr(obj) # in a script
或者print obj
对于你的类,定义__str__
或__repr__
方法。引用自Python官方文档:
__repr__(self)
被内置函数repr()
和字符串转换(反引号)调用,计算对象的“官方”字符串表示。如果可能的话,这应该看起来像一个有效的Python表达式,可以使用该表达式重新创建具有相同值的对象(在适当的环境中)。如果不可能,请返回像“<...一些有用的描述...>”这样的字符串形式。返回值必须是一个字符串对象。如果一个类定义了repr()但没有定义__str__()
,那么__repr__()
也会在需要该类实例的“非正式”字符串表示时使用。通常用于调试,因此重要的是表示信息丰富且无歧义。
__str__(self)
被内置函数str()
和print语句调用,计算对象的“非正式”字符串表示。这与__repr__()
不同,因为它不必是有效的Python表达式:可以使用更方便或更简洁的表示方法。返回值必须是一个字符串对象。
print "DEBUG: object value: " + repr(obj)
。 - AlejandroVDhelp(your_object)
。
help(dir)
。
If called without an argument, return the names in the current scope.
Else, return an alphabetized list of names comprising (some of) the attributes
of the given object, and of attributes reachable from it.
If the object supplies a method named __dir__, it will be used; otherwise
the default dir() logic is used and returns:
for a module object: the module's attributes.
for a class object: its attributes, and recursively the attributes
of its bases.
for any other object: its attributes, its class's attributes, and
recursively the attributes of its class's base classes.
help(vars)
Without arguments, equivalent to locals().
With an argument, equivalent to object.__dict__.
可能值得一试 --
Python是否有类似于Perl的Data::Dumper的工具?
我建议使用这个 --
https://gist.github.com/1071857
请注意,Perl有一个称为Data::Dumper的模块,可以将对象数据转换回Perl源代码(注意:它并不将代码转换回源代码,并且几乎始终不希望在输出中使用对象方法函数)。这可用于持久性,但常见目的是进行调试。
标准的Python pprint无法实现许多功能,特别是在看到对象实例时会停止下降并给出对象的内部十六进制指针(那个指针实际上并没有什么用途)。因此,简而言之,Python的设计理念都在于这种伟大的面向对象范例,但是你开箱即用的工具却不是专门用于处理对象的。
Perl的Data::Dumper允许您控制深度,还会检测循环链接结构(这真的很重要)。在Perl中,这个过程基本上更容易实现,因为对象除了它们的祝福(一个普遍定义的过程)之外没有特别的魔力。
在大多数情况下,使用__dict__
或dir()
可以获取你想要的信息。如果你需要更多细节,标准库包括inspect模块,它允许你获取一些令人印象深刻的详细信息。一些真正有用的信息包括:
如果你只是想知道“我的对象有哪些属性值?”,那么dir()
和__dict__
可能已经足够了。如果你真的想深入探索任意对象的当前状态(请记住,在Python中几乎所有东西都是对象),那么考虑使用inspect
模块。