0

I'm working on a simulation of a cluster of solar panels (a system/container). The properties of this cluster are linked almost one-to-one to the properties of the elements -- the panels (subsystem/contained) -- via the number of elements per cluster. E.g. the energy production of the cluster is simply the number of panels in the cluster times the production of the single cluster. Same for the cost, weight, etc. My question is how the link the container class to the contained class.

Let me illustrate with a naive example approach:

class PanelA(BasePanel):
    ... _x,_y,_area,_production,etc.

    @property
    def production(self):
        # J/panel/s
        return self._area * self._efficiency

    ... and 20 similar properties

    @property
    def _technical_detail

class PanelB(BasePanel):
    .... similar

class PanelCluster():
    ....        
    self.panel = PanelA()
    self.density = 100 # panels/ha

    @property
    def production(self):
        # J/ha/h

        uc = 60*60 # unit conversion
        rho = self.density
        production_single_panel = self.panel.production

        return uc*rho*production_single_panel

    ... and e.g. 20 similar constructions

Note, in this naive approach one would write e.g. 20 such methods which seems not in line with this DRY-principle.

What would be a better alternative? (Ab)Use getattr?

For example?

class Panel():
     unit = {'production':'J/panel/s'}

class PanelCluster():
     panel = Panel()

     def __getattr__(self,key):

        if self.panel.__hasattr__(key)
            panel_unit = self.panel.unit[key]

            if '/panel/s' in panel_unit:

                uc = 60*60 # unit conversion
                rho = self.density
                value_per_panel = getattr(self.panel,key)

                return uc*rho*value_per_panel
            else:
                return getattr(self.panel,key)

This already seems more 'programmatic' but might be naive -- again. So I wonder what are the options and the pros/cons thereof?

balletpiraat
  • 206
  • 1
  • 11

1 Answers1

1

There are a number of Python issues with your code, e.g.:

  • yield means something specific in Python, probably not a good identifier

and it's spelled:

  • hasattr(self.panel.unit, key)
  • getattr(self.panel, key)

That aside, you're probably looking for a solution involving inheritance. Perhaps both Panel and PanelCluster need to inherit from a PanelFunction class?

class PanelFunctions(object):
    @property
    def Yield(...):
        ...

class Panel(PanelFunctions):
    ..

class PanelCluster(PanelFunctions):
    ..

I would leave the properties as separte definitions since you'll need to write unit tests for all of them (and it will be much easier to determine coverage that way).

thebjorn
  • 26,297
  • 11
  • 96
  • 138
  • Thank you -- I've fixed those language errors: you can tell I am new to this. – balletpiraat Oct 04 '17 at 08:54
  • Welcome to Python. If you haven't done so already.. try `import this` at a python prompt.. :-) – thebjorn Oct 04 '17 at 08:57
  • I think this solution involving inheritance would come out similar to the first example I give: you write (most of) all of the mappings out. Which is an explicit proper way to do so. I am still curious for alternative solutions. – balletpiraat Oct 04 '17 at 09:03
  • I`m going to print out this Zen of Python btw, it makes more sense now after trying to do some more complex things. – balletpiraat Oct 04 '17 at 09:05