简体   繁体   中英

Python - Iterating over nested objects

What is an elegant way to iterate the nested object in Python? I am currently using nested loop as below.

for job in jobs:
    for task in job.tasks:
        for command in task.commands:
            print command.actual_cmd

Is there a better way which is more Pythonic?

You can set up chained generators to keep the indentation level down.

iter_tasks = (task for job in jobs for task in job.tasks)
iter_commands = (command for task in iter_tasks for command in task.commands)

for command in iter_commands:
    print(command.actual_cmd)

I agree with OldBunny2800 that in the case of three nested loops chaining generators may not gain you much in terms of readability.

If your nested logic goes deeper than that, the generators start to become attractive. Not only is the indentation level kept in check, you can also assign a meaningful variable name to each generator, effectively giving for loops a name.

It is pythonic . Already.

But if you worry about this goes to 10+ levels deep, with only the innermost loop has anything interesting, one thing you can consider is to create a generator. Your code can become:

def get_command(jobs):
    for job in jobs:
        for task in job.tasks:
            for command in task.commands:
                yield command

for command in get_command(jobs):
    print command.actual_cmd

So the whole purpose is to avoid excessive indentation.

To make it generic for multiple level, so you don't worry even if it is 100+ levels deep:

def get_nested(objlist, attribs):
    for x in objlist:
        if len(attribs) == 0:
            yield x
        else:
            x_dot_attr = getattr(x, attribs[0])
            for y in get_nested(x_dot_attr, attribs[1:]):
                yield y

for command in get_nested(jobs, ["tasks", "commands"]):
    print command.actual_cmd

But no, this generalization doesn't make it more pythonic. It only avoids excessive indentation.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM