这里我要找的是PHP的print_r函数。
这样我就可以通过查看有问题的对象的状态来调试脚本。
这里我要找的是PHP的print_r函数。
这样我就可以通过查看有问题的对象的状态来调试脚本。
当前回答
试试beeprint吧。
它不仅可以帮助你打印对象变量,还可以帮助你输出漂亮的结果,就像这样:
class(NormalClassNewStyle):
dicts: {
},
lists: [],
static_props: 1,
tupl: (1, 2)
其他回答
def dump(obj):
for attr in dir(obj):
print("obj.%s = %r" % (attr, getattr(obj, attr)))
有许多第三方函数根据作者的喜好添加了异常处理、国家/特殊字符打印、递归嵌套对象等功能。但它们基本上都可以归结为这个。
也许值得一查——
Python中是否存在与Perl的Data:: dump相同的程序?
我的建议是——
https://gist.github.com/1071857
注意,perl有一个名为Data::Dumper的模块,它将对象数据转换回perl源代码(注意:它不将代码转换回源代码,而且几乎总是你不想在输出中使用对象方法函数)。这可以用于持久性,但常见的目的是用于调试。
标准的python pprint有很多事情无法实现,特别是当它看到一个对象的实例时,它只是停止下降,并给你对象的内部十六进制指针(errr,顺便说一下,这个指针并没有很多用处)。所以简而言之,python就是这个伟大的面向对象范式,但是你从盒子里拿出来的工具是为处理对象以外的东西而设计的。
perl Data::Dumper允许你控制你想要去的深度,还可以检测循环链接结构(这真的很重要)。这个过程在perl中更容易实现,因为对象除了它们的祝福之外没有任何特殊的魔力(一个普遍定义良好的过程)。
Vars()似乎显示了该对象的属性,但dir()似乎也显示了父类(es)的属性。您通常不需要看到继承的属性,如str, doc。dict等等。
In [1]: class Aaa():
...: def __init__(self, name, age):
...: self.name = name
...: self.age = age
...:
In [2]: class Bbb(Aaa):
...: def __init__(self, name, age, job):
...: super().__init__(name, age)
...: self.job = job
...:
In [3]: a = Aaa('Pullayya',42)
In [4]: b = Bbb('Yellayya',41,'Cop')
In [5]: vars(a)
Out[5]: {'name': 'Pullayya', 'age': 42}
In [6]: vars(b)
Out[6]: {'name': 'Yellayya', 'age': 41, 'job': 'Cop'}
In [7]: dir(a)
Out[7]:
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
...
...
'__subclasshook__',
'__weakref__',
'age',
'name']
是否有内置函数打印对象的所有当前属性和值?
不。投票最多的答案排除了某些类型的属性,而接受的答案显示了如何获取所有属性,包括方法和部分非公共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,你也在修改对象本身的__dict__。
vars(obj)['quux'] = 'WHAT?!'
vars(obj)
返回:
{'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只返回与对象相关的所有(实际上是大部分)名称。
检查。评论中提到的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': ''}
警告
但也许我们知道我们的房产并不贵。我们可能想要改变逻辑以包括它们。也许我们希望排除其他自定义数据描述符。
然后我们需要进一步定制这个函数。因此,我们不能有一个内置函数神奇地知道我们想要什么并提供它。这是我们需要自己创造的功能。
结论
没有内置函数可以做到这一点,您应该根据自己的情况选择语义上最合适的方法。
试试beeprint吧。
它不仅可以帮助你打印对象变量,还可以帮助你输出漂亮的结果,就像这样:
class(NormalClassNewStyle):
dicts: {
},
lists: [],
static_props: 1,
tupl: (1, 2)