递归转储对象

时间:2013-05-03 08:17:01

标签: python

我不确定是否有标准方法可以做到这一点。我已经实现了以下函数来转储对象的所有内容。它必须递归转储子对象,所以我正在检查InstanceType,但它不起作用:

import types

def dump_obj(obj, level=0):
    for a in dir(obj):
        try:
            if type(obj.__dict__[a]) == types.InstanceType:
                dump_obj(obj.__dict__[a], level + 2)
            else:
                try:
                    print " " * level + "%s -> %s" % (a, obj.__dict__[a])
                except:
                    pass
        except:
            pass

如何验证元素本身是否为对象?

我真正想要的是以下内容。给出:

class B:
  def __init__(self):
    self.txt = 'bye'

class A:
  def __init__(self):
    self.txt = 'hello'
    self.b = B()

a = A()

dump_obj(a)

我想要以下输出:

txt -> hello
  txt -> bye

3 个答案:

答案 0 :(得分:9)

这将以递归方式转储任何对象和所有子对象。其他答案适用于简单的示例,但对于复杂的对象,它们缺少一些数据。

import jsonpickle # pip install jsonpickle
import json

serialized = jsonpickle.encode(obj)
print(json.dumps(json.loads(serialized), indent=2))

编辑:如果您使用YAML格式,它将更接近您的示例。

import yaml # pip install pyyaml
print(yaml.dump(yaml.load(serialized), indent=2))

答案 1 :(得分:7)

你的代码对我有用,除了事情以错误的顺序打印(内部优先,这是我实际上对递归的期望)。

所以,我改变了顺序(并使用了isinstance()以及迭代__dict__):

import types

def dump_obj(obj, level=0):
    for key, value in obj.__dict__.items():
        if not isinstance(value, types.InstanceType):
             print " " * level + "%s -> %s" % (key, value)
        else:
            dump_obj(value, level + 2)

class B:
  def __init__ (self):
    self.txt = 'bye'

class A:
  def __init__(self):
    self.txt = 'hello'
    self.b = B()

a = A()

dump_obj(a)

产生

txt -> hello
  txt -> bye

答案 2 :(得分:2)

最好使用isinstance(x, y)代替type(x) == y

由于一切都是Python中的对象,因此isinstance(attr, object)没有意义,因为(我猜)它总是返回true。

你最好的选择是将某些类型“列入黑名单”。例如,您检查是否除int, float, str, unicode, list, dict, set, ...之外的其他内容更深,否则您只需打印它。

例如:

def dump(obj, level=0):
   for attr in dir(obj):
      val = getattr(obj, a)
      if isinstance(val, (int, float, str, unicode, list, dict, set)):
           print level*' ', val
      else:
           dump(val, level=level+1)

UPDATE isinstance考虑了继承,因此如果您尝试查看对象是否是父类的实例,它将返回True,而在使用类型时它可能不会

因为在这种情况下你将测试原始类型,在这种情况下它可能没有任何区别,但总的来说isinstance更好。

见这个例子:

>>> class A(object): pass
... 
>>> class B(A): pass
... 
>>> a, b = A(), B()
>>> type(a)
<class '__main__.A'>
>>> type(a) == A
True
>>> type(b)
<class '__main__.B'>
>>> type(b) == B
True
>>> type(b) == A
False
>>> 

您可以查看docs