2013-05-03 88 views
7

我不确定是否存在执行此操作的标准方法。我已经实现了以下功能来转储对象的所有内容。它必须递归地转储子对象,所以我检查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 
+0

一切都是在Python一个对象。 – Matthias 2013-05-03 08:18:27

+0

好的:我如何验证一个元素是否是'types.InstanceType'(或其他需要的),这样我可以触发递归? – dangonfast 2013-05-03 08:19:37

回答

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) 

UPDATEisinstance考虑到继承,所以如果你尝试看看,如果对象是一个父类的实例,它会返回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

+0

谢谢,我结束了类似这样的事情,但使用'type()=='。你能否详细说明为什么使用'isinstance'更好? – dangonfast 2013-05-03 08:44:26

+0

你是对的,我的例子被简化了:实际上我想从标准库转储复杂的对象,所以你的警告是相关的。另一方面,'getattr'也返回方法和其他东西,这会导致无限递归。 – dangonfast 2013-05-03 09:12:45

+0

@gonvaled哦,不错的发现:) – jadkik94 2013-05-03 09:34:34

5

您的代码对我的作品,但事情变得印刷错误的顺序(内第一,这是我居然会期待与递归)。

于是,我改变了顺序(以及在__dict__使用isinstance()以及迭代):

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

这适用于简单的例子,但对于一个复杂的对象,它缺少一些数据子对象。 – wisbucky 2016-03-04 19:12:28

5

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

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) 
+2

这应该是被接受的答案 – 2017-03-13 18:04:58