Search code examples
pythonclassfor-loopinstance-variables

Changing instance attributes in for loop in method


I have a problem where I want to change the class of some child elements in a class recursively.

I have a working solution, which is the following:

class PerformanceAggregator:
    def __init__(self, collection: pf.GenericPortfolioCollection):
        self.collection = collection
        self.change_children()

    def __getattr__(self, item):
        return getattr(self.collection, item, None)

    def change_children(self):
        for i in range(len(self.children)):
            if isinstance(self.children[i], pf.GenericPortfolioCollection):
                self.children[i] = PerformanceAggregator(self.children[i])

However, the change_children method is not very pythonic. It would be better with

class PerformanceAggregator2:
    def __init__(self, collection: pf.GenericPortfolioCollection):
        self.collection = collection
        self.change_children()

    def __getattr__(self, item):
        return getattr(self.collection, item, None)

    def change_children(self):
        for child in self.children:
            if isinstance(child, pf.GenericPortfolioCollection):
                child = PerformanceAggregator(child)

But this method does not work as intended. It does not replace the "child" element as the first method does. Do anybody have an idea about what is wrong?


Solution

  • When you're looping through self.children, you're assigning child to PerformanceAggregator(child) but not necessarily updating the child element in self.children.

    This should work:

         def change_children(self):
             for (val,child) in enumerate(self.children):
                 if isinstance(child, pf.GenericPortfolioCollection):
                     self.children[val] = PerformanceAggregator(child)