Итеративно создавать подкласс и сохранять объекты как атрибут класса - PullRequest
1 голос
/ 25 мая 2020

У меня есть класс, который выполняет некоторые сложные вычисления и генерирует некоторый результат MyClass.myresults.

MyClass.myresults на самом деле сам класс с разными атрибутами (например, MyClass.myresults.mydf1, MyClass.myresults.mydf2.

Теперь мне нужно запустить MyClass итеративно, следуя списку сценариев ios (scenarios=[1,2,[2,4], 5].

Это происходит с простым l oop:

    for iter in scenarios:
        iter = [iter] if isinstance(iter, int) else iter
        myclass = MyClass() #Initialize MyClass
        myclass.DoStuff(someInput) #Do stuff and get results
        results.StoreScenario(myclass.myresults, iter)

и в конце каждой итерации хранить MyClass.myresults.

Я хотел бы создать отдельный класс (Results), который на каждой итерации создает подкласс scenario_1, scenario_2, scenario_2_4 и сохраняет в нем MyClass.myresults.

class Results:
    # no initialization, is an empty container to which I would like to add attributes iteratively
    class StoreScenario:
        def __init__(self, myresults, iter):
            self.'scenario_'.join(str(iter)) = myresults #just a guess, I am assuming this is wrong

Предложения по различным подходам более чем приветствуются, я новичок в классах и не уверен, приемлем ли это подход или я делаю что-то ужасное (неуклюже, неэффективно с памятью или еще ).

Ответы [ 2 ]

1 голос
/ 27 мая 2020

Итак, я решил это, используя setattr :

class Results:

    def __init__(self):
        self.scenario_results= type('ScenarioResults', (), {}) # create an empty object


    def store_scenario(self, data, scenarios):
        scenario_key = 'scenario_' + '_'.join(str(x) for x in scenarios)
        setattr(self.simulation_results, scenario_key, 
                subclass_store_scenario(data))

class subclass_store_scenario:
    def __init__(self, data):

        self.some_stuff = data.result1.__dict__
        self.other_stuff = data.result2.__dict__

Это позволяет мне вызывать такие вещи, как:

results.scenario_results.scenario_1.some_stuff.something
results.scenario_results.scenario_1.some_stuff.something_else

Это необходимо мне, поскольку мне нужно для вычисления других показателей, сводных или специфичных для сценария c, которые я затем могу итеративно назначать, используя снова setattr:

    def construct_measures(self, some_data, configuration):
        for scenario in self.scenario_results: 
            #scenario is a reference to the self.scenario_results class. 
            #we can simply add attributes to it
            setattr(scenario , 'some_measure',
                    self.computeSomething(
                            some_data.input1, some_data.input2))

1 голос
/ 25 мая 2020

Есть две проблемы использования этого подхода. Первая: Результат класс (отдельный класс) сохраняет только измененные значения вашего класса MyClass , я имею в виду, они должны быть тот же класс.

Вторая проблема - это эффективность памяти , вы создаете один и тот же объект дважды для хранения фактических и измененных значений на каждой итерации.

Предлагаемый подход использует hashmap или словарь в python. Используя словарь , вы можете очень эффективно хранить копии измененного объекта, и нет необходимости создавать другой класс.

class MyClass:
  def __init__(self):
    # some attributes ...
    self.scenarios_result = {}

superObject = MyClass()

for iter in scenarios:

    iter = [iter] if isinstance(iter, int) else iter

    myclass = MyClass() #Initialize MyClass
    myclass.DoStuff(someInput) #Do stuff and get results

    # results.StoreScenario(myclass.myresults, iter)

    superObject.scenarios_result[iter] = myclass
...