1

I have been told that I should avoid to use self.__dict__ in my code but I can't find another way around for what I am trying to do. I just begin to work with classes so not too sure how to do this.

class variable( object ):
    def __init__( self, json_fn, *args, **kwargs ):

        self.metrics = self.getmetrics(json_fn)
        for metric in self.metrics :
            self.__dict__[metric] = self.get_metric_dataframes(metric)

    def get_metric_dataframes( self , metric_name ):
        '''extract and return the dataframe for a metric'''

So my object "variable" has different dataframes for different metrics stored in the json. I wanted to be able to do variable.temperature, variable.pressure , variable.whatever without having to write :

self.temperature = self.get_metric_dataframes(temperature)
self.pressure = self.get_metric_dataframes(pressure)
self.whatever = self.get_metric_dataframes(whatever)

Since all the dataframes are extracted with the same function taking the metric as arguments. Which is why I looped through the metrics and use

self.__dict__[metric] = self.get_metric_dataframes(metric)

So Knowing that I will never update any of those dataframes (I use copies of them in the code but don't want to update the values of the object).

Is there another solution?

The other way i could do would be to build a dictionnary with all the metric as key and dataframe as values and store it in self.metric, I could then call it with object.metric['temperature'] but I would rather do object.temperature right away and I am kind of curious to know if that can be done.

Thank you for your help!

  • You might be able to use `setattr()`, but I'm not sure why you were told to avoid `self.__dict__`. – kindall Oct 10 '16 at 23:19

2 Answers2

3

Provided each metric is a string, you can use setattr in place of a direct access to your instance dictionary:

for metric in self.metrics:
     setattr(self, metric, self.get_metric_dataframes(metric))
Moses Koledoye
  • 77,341
  • 8
  • 133
  • 139
1

There are several solutions:

  • using __getattr__ but you may run into difficulties (implementation can be non trivial)
  • using properties: elegant and classic solution,
  • using descriptors: can be difficult to debug if you are note familiar with this.

Finally, your solution with __dict__ is quite good. You can also use getattr/setattr.

Another solution is to store your metrics in your own dict:

self.metric_dict = {metric: self.get_metric_dataframes(metric) for metric in metrics}

And then define properties to access this dictionary like attributes

@property
def temperature(self):
    return self.metric_dict["temperature"]

And so on…

Laurent LAPORTE
  • 21,958
  • 6
  • 58
  • 103
  • That seems to be a bit more work than Moses's answer but that is an interesting way as well, thank you I will look a bit deeper into it. – User18981898198119 Oct 10 '16 at 23:36