Reputation: 117
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
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