在Python中递归打印对象的所有属性,列表,字典等

问题描述 投票:0回答:2

使用Python 2.7.10,我有这个脚本:

#!/usr/bin/python

#Do `sudo pip install boto3` first
import boto3
import json

def generate(key, value):
    """
    Creates a nicely formatted Key(Value) item for output
    """
    return '{}={}'.format(key, value)

def main():
    ec2 = boto3.resource('ec2', region_name="us-west-2")
    volumes = ec2.volumes.all()
    for vol in volumes:
        #print(vol.__str__())
        #print(vol.__dict__)
        print vol

     # vol object has many attributes, which can be another class object. 
     # For ex:
            #vol.volume_id),
            #vol.availability_zone),
            #vol.volume_type),

        # only process when there are tags to process
        # HERE: tags is another object which can contain a dict/list
        #if vol.tags:
        #    for _ in vol.tags:
        #        # Get all of the tags
        #        output_parts.extend([
        #            generate(_.get('Key'), _.get('Value')),
        #        ])


        # output everything at once.
        print ','.join(output_parts)

if __name__ == '__main__':
    main()

是否有一个函数可以使用一次调用递归地打印所有对象的属性?如何在一次调用中打印 val.xxxxx 和 val.tags.xxxx 的值。

我尝试使用

.__dict__
.__str__()
打印对象,但没有帮助。

python python-2.7 object recursion
2个回答
7
投票

这是一个函数,您可以将其放入对象的 str 中。 您也可以直接调用它,传入您想要打印的对象。 该函数返回一个字符串,表示对象内容的格式良好的遍历。

感谢来自forum.pythonistacafe.com 的@ruud 提出了这个解决方案。

def obj_to_string(obj, extra='    '):
    return str(obj.__class__) + '\n' + '\n'.join(
        (extra + (str(item) + ' = ' +
                  (obj_to_string(obj.__dict__[item], extra + '    ') if hasattr(obj.__dict__[item], '__dict__') else str(
                      obj.__dict__[item])))
         for item in sorted(obj.__dict__)))


class A():
    def __init__(self):
        self.attr1 = 1
        self.attr2 = 2
        self.attr3 = 'three'


class B():
    def __init__(self):
        self.a = A()
        self.attr10 = 10
        self.attrx = 'x'


class C():
    def __init__(self):
        self.b = B()


class X():

    def __init__(self):
        self.abc = 'abc'
        self.attr12 = 12
        self.c = C()

    def __str__(self):
        return obj_to_string(self)


x = X()

print(x)

输出:

<class '__main__.X'>
    abc = abc
    attr12 = 12
    c = <class '__main__.C'>
        b = <class '__main__.B'>
            a = <class '__main__.A'>
                attr1 = 1
                attr2 = 2
                attr3 = three
            attr10 = 10
            attrx = x

0
投票

功能

这不是我的(我忘记了作者),但经过重新设计以更好地理解。您可以使用 attrs Define 和 asdict 递归创建参数字典

from typing import Any


def rec_print(map_obj: dict | Any):
    # Tree variants
    end_tree = "└─ "
    pipe_tree = "│  "
    tee_tree = "├─ "
    blank_tree = "   "

    # Process object repr to pretty print
    def _clear_obj_repr(obj):
        return repr(obj).split("at")[0].replace("<", "").replace(">", "").strip()

    # Recursive tree get
    def _get_recursive_repr(map_obj: dict | Any, name: str = "", header: str = "", last=True):
        # End point in recursion
        if not isinstance(map_obj, dict):
            if "<" in repr(map_obj):
                obj_repr = _clear_obj_repr(map_obj)
            else:
                obj_repr = repr(map_obj)

            return f"{header}{end_tree if last else tee_tree}{name}: {obj_repr}\n"

        # Continue recursion
        result = f"{header}{end_tree if last else tee_tree}{name}\n" # Header of local/global tee
        last_key = list(map_obj.keys())[-1]
        for key, value in map_obj.items():
            inner_result = _get_recursive_repr(
                value,
                name=key,
                header=f"{header}{blank_tree if last else pipe_tree}",
                last=key == last_key,
            )

            result += inner_result[6:] # Add tree leaf, delete first 6 symbols to shift left all tree

        return result

    result = _get_recursive_repr(map_obj)
    print(result[4:]) # Delete first empty header

示例:

rec_print(
    dict(
        f=dict(b=lambda x: x * 2),
        a=1234,
        n=dict(
            p=3,
            g=dict(a=2, h=5),
        ),
    )
)

出:

f
└─ b: function lambda
a: 1234
n
├─ p: 3
└─ g
   ├─ a: 2
   └─ h: 5

对于 attrs 类

from attrs import define, asdict


@define
class A:
    g: str = "wq"
    q: int = 2


@define
class T:
    d: int = 3
    g: A = A()


a = T()
rec_print(asdict(a))

出:

d: 3
g
├─ g: 'wq'
└─ q: 2
© www.soinside.com 2019 - 2024. All rights reserved.