重写函数在python中显示复杂的递归字典(更通用)

2024-06-16 12:19:23 发布

您现在位置:Python中文网/ 问答频道 /正文

函数输入是一个复杂的字典:

[{'blacklist': [{'devnode': '"^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"'}, {'devnode': '"^hd[a-z][[0-9]*]"'}, {'devnode': '"^cciss!c[0-9]d[0-9]*"'}]}, {'defaults': [{'user_friendly_names': 'yes'}]}, {'defaults': [{'udev_dir': '/dev'}, {'polling_interval': '10'}, {'selector': '"round-robin 0"'}, {'path_grouping_policy': 'multibus'}, {'getuid_callout': '"/sbin/scsi_id -g -u -s /block/%n"'}, {'prio_callout': 'none'}, {'path_checker': 'readsector0'}, {'rr_min_io': '100'}, {'max_fds': '8192'}, {'rr_weight': 'priorities'}, {'failback': 'immediate'}, {'no_path_retry': 'fail'}, {'user_friendly_names': 'yes'}]}, {'blacklist': [{'wwid': '26353900f02796769'}, {'devnode': '"^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"'}, {'devnode': '"^hd[a-z]"'}]}, {'devices': [{'device': [{'vendor': '"COMPAQ "'}, {'product': '"HSV110 (C)COMPAQ"'}, {'path_grouping_policy': 'multibus'}, {'getuid_callout': '"/sbin/scsi_id -g -u -s /block/%n"'}, {'path_checker': 'readsector0'}, {'path_selector': '"round-robin 0"'}, {'hardware_handler': '"0"'}, {'failback': '15'}, {'rr_weight': 'priorities'}, {'no_path_retry': 'queue'}]}, {'device': [{'vendor': '"COMPAQ "'}, {'product': '"MSA1000 "'}, {'path_grouping_policy': 'multibus'}]}]}]

我想出了这个函数,使它看起来像它应该有很好的凹痕:

def pretty(d, indent=0):
for i in d:
    for key, value in i.items():
        print('\t' * indent + str(key) + ' {')
        if isinstance(value, list):
            for item in value:
                if isinstance(item, dict):
                    for key_1, value_1 in item.items():
                        if isinstance(value_1, list):
                            print('\t' * (indent + 2) + str(key_1) + ' {')
                            for x in value_1:
                                for key_2, value_2 in x.items():
                                    print('\t' * (indent + 3) + str(key_2) + 4 * ' ' + str(value_2))
                            print('\t' * (indent + 2) + '}')
                        else:
                            print('\t' * (indent + 1) + str(key_1) + 4 * ' ' + str(value_1))

        print('}')

工作正常,输出很好:

    blacklist {
    devnode    "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
    devnode    "^hd[a-z][[0-9]*]"
    devnode    "^cciss!c[0-9]d[0-9]*"
}
defaults {
    user_friendly_names    yes
}
defaults {
    udev_dir    /dev
    polling_interval    10
    selector    "round-robin 0"
    path_grouping_policy    multibus
    getuid_callout    "/sbin/scsi_id -g -u -s /block/%n"
    prio_callout    none
    path_checker    readsector0
    rr_min_io    100
    max_fds    8192
    rr_weight    priorities
    failback    immediate
    no_path_retry    fail
    user_friendly_names    yes
}
blacklist {
    wwid    26353900f02796769
    devnode    "^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"
    devnode    "^hd[a-z]"
}
devices {
        device {
            vendor    "COMPAQ "
            product    "HSV110 (C)COMPAQ"
            path_grouping_policy    multibus
            getuid_callout    "/sbin/scsi_id -g -u -s /block/%n"
            path_checker    readsector0
            path_selector    "round-robin 0"
            hardware_handler    "0"
            failback    15
            rr_weight    priorities
            no_path_retry    queue
        }
        device {
            vendor    "COMPAQ "
            product    "MSA1000 "
            path_grouping_policy    multibus
        }
}

但是我的函数只有“2层”深,如果有像devces{device{item{}}}这样的东西,你知道如何使函数更通用吗?你知道吗


Tags: pathkeyinforvaluepolicyrrprint
2条回答

使用json包。试试这个:

import json

d = [{'blacklist': [{'devnode': '"^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"'}, {'devnode': '"^hd[a-z][[0-9]*]"'}, {'devnode': '"^cciss!c[0-9]d[0-9]*"'}]}, {'defaults': [{'user_friendly_names': 'yes'}]}, {'defaults': [{'udev_dir': '/dev'}, {'polling_interval': '10'}, {'selector': '"round-robin 0"'}, {'path_grouping_policy': 'multibus'}, {'getuid_callout': '"/sbin/scsi_id -g -u -s /block/%n"'}, {'prio_callout': 'none'}, {'path_checker': 'readsector0'}, {'rr_min_io': '100'}, {'max_fds': '8192'}, {'rr_weight': 'priorities'}, {'failback': 'immediate'}, {'no_path_retry': 'fail'}, {'user_friendly_names': 'yes'}]}, {'blacklist': [{'wwid': '26353900f02796769'}, {'devnode': '"^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"'}, {'devnode': '"^hd[a-z]"'}]}, {'devices': [{'device': [{'vendor': '"COMPAQ "'}, {'product': '"HSV110 (C)COMPAQ"'}, {'path_grouping_policy': 'multibus'}, {'getuid_callout': '"/sbin/scsi_id -g -u -s /block/%n"'}, {'path_checker': 'readsector0'}, {'path_selector': '"round-robin 0"'}, {'hardware_handler': '"0"'}, {'failback': '15'}, {'rr_weight': 'priorities'}, {'no_path_retry': 'queue'}]}, {'device': [{'vendor': '"COMPAQ "'}, {'product': '"MSA1000 "'}, {'path_grouping_policy': 'multibus'}]}]}]

print(json.dumps(d, indent=4))

其中json.dumps命令接受字典d,并在每个缩进中缩进4个空格字符(当然也可以由您选择)。你知道吗

编辑:

如果希望输出与问题中的结果完全相同,则应使用以下递归函数:

def parse(data, indent=0):
    if not isinstance(data, list):
        data = [data]

    for d in data:
        for key, val in d.items():
            if isinstance(val, list):
                print(" "*4*indent + key + "{ ")
                parse(val, indent + 1)
                print(" "*4*indent + "}")
            else:
                print("{}{}{}{}" .format(
                    " "*4*indent, key, " "*(30-len(key)), val))

data = [{'blacklist': [{'devnode': '"^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"'}, {'devnode': '"^hd[a-z][[0-9]*]"'}, {'devnode': '"^cciss!c[0-9]d[0-9]*"'}]}, {'defaults': [{'user_friendly_names': 'yes'}]}, {'defaults': [{'udev_dir': '/dev'}, {'polling_interval': '10'}, {'selector': '"round-robin 0"'}, {'path_grouping_policy': 'multibus'}, {'getuid_callout': '"/sbin/scsi_id -g -u -s /block/%n"'}, {'prio_callout': 'none'}, {'path_checker': 'readsector0'}, {'rr_min_io': '100'}, {'max_fds': '8192'}, {'rr_weight': 'priorities'}, {'failback': 'immediate'}, {'no_path_retry': 'fail'}, {'user_friendly_names': 'yes'}]}, {'blacklist': [{'wwid': '26353900f02796769'}, {'devnode': '"^(ram|raw|loop|fd|md|dm-|sr|scd|st)[0-9]*"'}, {'devnode': '"^hd[a-z]"'}]}, {'devices': [{'device': [{'vendor': '"COMPAQ "'}, {'product': '"HSV110 (C)COMPAQ"'}, {'path_grouping_policy': 'multibus'}, {'getuid_callout': '"/sbin/scsi_id -g -u -s /block/%n"'}, {'path_checker': 'readsector0'}, {'path_selector': '"round-robin 0"'}, {'hardware_handler': '"0"'}, {'failback': '15'}, {'rr_weight': 'priorities'}, {'no_path_retry': 'queue'}]}, {'device': [{'vendor': '"COMPAQ "'}, {'product': '"MSA1000 "'}, {'path_grouping_policy': 'multibus'}]}]}]

parse(data)

递归!你知道吗

您需要编写函数,使其能够调用自身:

INDENT_STEP = 4


def print_indented(indent, *args, **kwargs):
    """
    Prints anything with `indent` spaces before it.
    Passes arguments to builtin print.
    """
    print((" " * indent), *args, **kwargs)


def print_list(items, indent):
    print("{")
    for value in items:
        print_formatted(value, indent)
    print_indented(indent, "}")


def print_dict(dictionary, indent):
    """Prints each key and value of a dictionary, separated by a space."""
    for key, value in dictionary.items():
        child_indent = indent + INDENT_STEP
        print_indented(child_indent, key, "", end="")
        print_formatted(value, child_indent)


def print_formatted(item, indent=0):
    if isinstance(item, list):
        print_list(item, indent)
        return

    if isinstance(item, dict):
        print_dict(item, indent)
        return

    print(item)

相关问题 更多 >