notfreshprince
notfreshprince

Reputation: 117

Is there a better way to retrieve values than to iterate through the same loops?

To put it simply, I have a list of server classes, which contain a list of component classes, which contain a list of function classes. You see where this is going.

In my program I want to retrieve a value from each of the function classes, then use all of those values on each other, then add the resulting values back to the function classes. I end up repeatedly using the nested loops over and over.

Here's my code:

component_subscriptions = {}

for server in self.network.servers:
    for component in server.components:
        for function in component.functions:
            component_subscriptions[function.name] = []

for server in self.network.servers:
    for component in server.components:
        for function in component.functions:
            for subscription in function.subscriptions:
                if subscription.name in component_subscriptions.keys():
                    component_subscriptions[subscription.name].append(function.publish_address)

for server in self.network.servers:
    for component in server.components:
        for function in component.functions:
            print(function.name)
            if function.name in component_subscriptions.keys():
                function.subscribers.extend(component_subscriptions[function.name])

for server in self.network.servers:
    for component in server.components:
        for function in component.functions:
            if function.name in component_subscriptions.keys():
                function.subscribers = component_subscriptions[function.name]

Is there a way of reusing por simplifying the three-deep for loops? Am I missing something ridiculously obvious?

Upvotes: 1

Views: 30

Answers (1)

youknowone
youknowone

Reputation: 1074

A straight-forward way with generator:

def gen_functions(self):
    for server in self.network.servers:
        for component in server.components:
            for function in component.functions:
                yield function

for function in gen_functions(self):
    component_subscriptions[function.name] = []

for function in gen_functions(self):
    for subscription in function.subscriptions:
       if subscription.name in component_subscriptions.keys():
           component_subscriptions[subscription.name].append(function.publish_address)
...

About second loop, I prefer this way:

for function in gen_functions(self):
    for subscription in (component_subscriptions[s.name] for s in function.subscriptions if s.name in component_subscriptions):
        subscription.append(function.publish_address)

to reuse it, create another function:

def iter_function_subscriptions(function):
    for subscription in (component_subscriptions[s.name] for s in function.subscriptions if s.name in component_subscriptions):
        yield subscription

So combine them now:

for function in gen_funtions(self):
   for subscription in iter_function_subscriptions(function):
       subscriptoin.append(function.publish_address)

It is done, but you may want to add them to the function class.

# patching the class. it will be better if you can directly add this method into function class
type(function).iter_subscriptions = iter_function_subscriptions

Then,

for function in gen_funtions(self):
   for subscription in function.iter_subscriptions():
       subscription.append(function.publish_address)

Upvotes: 2

Related Questions