【问题标题】:Python pretty print nested objectsPython 漂亮的打印嵌套对象
【发布时间】:2018-08-08 19:03:43
【问题描述】:

我有 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()

【问题讨论】:

  • 既然您提到漂亮的打印,并使用标签pretty-print,我假设您只是想控制pprint 模块如何处理您的对象?最简单的做法是创建一个自定义的PrettyPrinter 子类,该子类覆盖其中记录的方法,因此它将您的对象作为“递归对象”处理,如列表和字典。然后,您只需使用该类的实例代替 pprint 模块。

标签: python pretty-print


【解决方案1】:

通过让您的类从实现__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】:

    以下递归函数使用__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
    

    【讨论】:

    • 正是我需要的,你
    • 我不是提问者
    • @slashdottir 哦好吧
    • PrettyPrinter 的东西都很好,但大多数时候你需要做的只是阅读该死的输出。谢谢你省了头疼。 +1
    【解决方案3】:

    如果你:

    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]
    

    【讨论】:

    • 甚至不工作。 TypeError:不能将序列乘以“str”类型的非整数
    猜你喜欢
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    • 2014-05-12
    • 1970-01-01
    • 2013-02-16
    • 2014-05-18
    • 1970-01-01
    相关资源
    最近更新 更多