Python漂亮的打印嵌套对象

时间:2018-08-08 19:03:43

标签: python pretty-print

我有3个python类A,B和C。A包含B对象,B包含C的对象。我想要的是当我打印一个类对象时,它应该以以下格式漂亮地打印。 C类内部也可以有更多嵌套。

A:
    loc : XYZ
    qual : ABC
    b :
        name : ABC
        age : 30
        c :
            address : ABC
            phn : 99009

下面是供参考的类。

class C(object):
    def __init__(self):
        self.address='ABC'
        self.phn=99009

class B(object):
    def __init__(self):
        self.name='ABC'
        self.age=30
        self.c = C()

class A(object):
    def __init__(self):
        self.loc = 'XYZ'
        self.qual = 'ABC'
        self.b = B()

3 个答案:

答案 0 :(得分:2)

以下递归函数使用__dict__ attr从头开始工作。类以获取key:value对类的属性。从这里开始,我们只是测试该值是否为另一个类(在这种情况下,我们将再次调用我们自己),否则,我们将简单地以您期望的格式打印它。

要跟踪的唯一另一件事是当前缩进该行当前打印的级别。可以使用默认参数(indent)轻松地完成此操作,我们可以在每次递归操作之前将其递增。

def pretty_print(clas, indent=0):
    print(' ' * indent +  type(clas).__name__ +  ':')
    indent += 4
    for k,v in clas.__dict__.items():
        if '__dict__' in dir(v):
            pretty_print(v,indent)
        else:
            print(' ' * indent +  k + ': ' + str(v))

它有效:

>>> pretty_print(A())
A:
    loc: XYZ
    qual: ABC
    B:
        name: ABC
        age: 30
        C:
            address: ABC
            phn: 99009

答案 1 :(得分:2)

以下方法通过让您的类从实现__str__方法的通用基类继承而实现:

class PrettyPrinter(object):
    def __str__(self):
        lines = [self.__class__.__name__ + ':']
        for key, val in vars(self).items():
            lines += '{}: {}'.format(key, val).split('\n')
        return '\n    '.join(lines)

class C(PrettyPrinter):
    def __init__(self):
        self.address='ABC'
        self.phn=99009

class B(PrettyPrinter):
    def __init__(self):
        self.name='ABC'
        self.age=30
        self.c = C()

class A(PrettyPrinter):
    def __init__(self):
        self.loc = 'XYZ'
        self.qual = 'ABC'
        self.b = B()

a = A()
print(a)

在Python 3.6及更高版本中,显示为

A:
    loc: XYZ
    qual: ABC
    b: B:
        name: ABC
        age: 30
        c: C:
            address: ABC
            phn: 99009

请注意,所有属性都会自动打印。它们的打印顺序由vars函数确定,该函数实际上在__dict__词典中显示。该字典在Python 3.5及更低版本中具有不确定的顺序,因此打印输出不如3.6及更高版本中的好。

答案 2 :(得分:0)

以防万一:

  1. 嵌入列表或字典
  2. 想要一个字符串结果而不是一个stdout.write
class C(object):
    def __init__(self):
        self.address='ABC'
        self.phn=99009
        self.my_list = [1, 2, 3, 4]
        self.my_dic = {1:2, 3:4}

print(str_pretty(C(), indent=2, key="self"))

c: (C)
    address: ABC
    phn: 99009
    my_list: (list)
    0: 1
    1: 2
    2: 3
    3: 4
    my_dic: (dict)
    1: 2
    3: 4
def str_pretty(obj, indent=1, rec=0, key=''):
    """Returns: pretty str of an object
    obj <- the object to print
    indent <- the indent per depth
    rec <- used in recursion
    """
    # Init
    s_indent = ' ' * indent * rec
    items = {}
    stg = s_indent

    if key != '': stg += str(key) + ': '

    # Discriminate && Check if final
    if isinstance(obj, list):
        items = enumerate(obj)
    elif isinstance(obj, dict):
        items = obj.items()
    elif '__dict__' in dir(obj):
        items = obj.__dict__.items()
    if not items:
        return stg + str(obj)

    # Recurse
    stg += '(' + type(obj).__name__ + ')\n'
    for k, v in items:
        stg += str_pretty(v, indent=indent, rec=rec+1, key=k) + "\n"

    # Return without empty lines
    return re.sub(r'\n\s*\n', '\n', stg)[:-1]