0

Having created a composite class in python, is there a (simple) way how to directly access the attributes/methods of the components? That is without specifying which component the attribute/method belongs to?

Here is the MWE:

class Component1:
    def __init__(self, data1):
        self.data1 = data1

    def add1(self):
        return self.data1 + 1

class Component2:
    def __init__(self, data2):
        self.data2 = data2

    def add2(self):
        return self.data2 + 2



class Composite:
    def __init__(self, data1, data2):
        self.component1 = Component1(data1)
        self.component2 = Component2(data2)


composite = Composite(data1, data2)

# Now I can access data1 (and data2)
# But it is really cumbersome
composite.component1.data1



# So I would like to have just
composite.data1

Is there a way to achieve this especially when the number of attributes and methods is high? I know I could add the property

@property
def data1(self):
    return self.component1.data1

but that would be painful with a high number of attributes and methods.

Edit:

Each component has different attributes/method names from each other. There also is not a common basis (eg, Component1().comp1_attibute_i or anything similar). The number at the end of the names is not present in the real problem (it was used just for simplification).

user64150
  • 59
  • 5
  • 1
    You would at the very least need to have a way to map out that `component1` has attribute `data1`. If all the subfields had the same name, you could iterate all the attributes of `Composite` and then access their common attribute. Without a common name though, I can't see how you could automate this without assuming something like the first found attribute is the one you're after. Unless you assume that any attribute ending in `1` has a sub-attribute ending in `1`, but that would be a bit of a fragile naming scheme I think. – Carcigenicate Jun 02 '21 at 15:52
  • @Carcigenicate: I have edited the question to clarify the naming conventions. If I understand you correctly, there is no way to "flatten" the hierarchy without providing a map? Could you point me to a direction how does this map would look like? And many thanks for a quick answer! Thank you for a quick answer. – user64150 Jun 03 '21 at 13:22
  • If you find yourself needing to access the components more often than the composite, it calls into question whether you need the composite in the first place. – chepner Jun 03 '21 at 13:22
  • 1
    @user64150 You could try to use the `__dict__` attribute of `Composite`. You could do a recursive flatten of each object's `__dict__` to get a flat dictionary of all attributes. That strikes me as a bit hacky and expensive though. I don't know of a clean, cheap way to achieve what you're after. – Carcigenicate Jun 03 '21 at 13:25
  • @chepner: The 1st component defines an optimization problem, the 2nd solves the optimization, and the 3rd computes outputs based on the optimization outcome (think of R2 after running an OLS). I thought it makes sense to wrap it up into a single class to have it all together, since it belongs together. But I am happy to use a diffent structure if it would make more sense – user64150 Jun 03 '21 at 13:32
  • Just because the three things are related doesn't mean you need to model that with a class. Are there any operations that require any interaction? It doesn't seem like your class does anything a simple tuple couldn't handle. – chepner Jun 03 '21 at 13:36

1 Answers1

0

Derive or use dictionaries for your class. One dictionary has the attributes, and one dictionary the methods.

So attribute access is composite["data1"].

Functions could be invoked via getattr. I don't know the details but there's some useful stuff here.

Kevin
  • 398
  • 2
  • 7