2

I have created four classes: experiment, experiment_type1, experiment_type2 and experiment_type3

experiment is an abstract class, it cannot be instantiated. It has 2 methods, __init__(self) and run(self) where run(self) is abstract.

experiment_type1 and experiment_type2 are derived from experiment. They inherit the __init__(self) from experiment (so they share the same constructor) but they implement run(self) differently from each other.

My problem is with experiment_type3 class. It also only has the run(self) method, implemented differently from experiment_type1 and experiment_type2, but its constructor takes an additional argument. Its constructor is of the form __init__(self, parameter)

Ideally I would like experiment_type3 to be derived from experiment. But there is a constructor mismatch. What is the best way to handle this? Programming in python in this case.

Edit: This is the code for experiment and experiment_type3. As you can see it depends on self.epsilon which does not exist.

import numpy as np from abc import ABC, abstractmethod from Bandit import Bandit

class experiment(ABC):
    def __init__(self, num_iter, bandit_list): #epsilon is the chance to explore, num_iter is num of iterations, bandit_list is the list of the bandits
        self.num_iter = num_iter
        self.bandit_list = bandit_list
        self.best_bandit = np.random.choice(len(bandit_list))

    @abstractmethod
    def run(self):
        raise NotImplementedError('derived class must implement run() method!')

class eg_experiment(experiment):
    def run(self):
        for iteration in range(self.num_iter):
            bandit = np.random.choice(len(self.bandit_list))
            if(np.random.random() > self.epsilon):
                bandit = self.best_bandit
            self.bandit_list[self.best_bandit].pull()
            self.best_bandit = np.argmax([bandit.current_mean for bandit in self.bandit_list])
Oria Gruber
  • 1,513
  • 2
  • 22
  • 44

2 Answers2

3

As the comments point out, using super() on the parent class's __init__ should give you what you want.

class A:
    def __init__(self, parameter)
        self.parameter = parameter

class B(A):
    def __init__(self, parameter, new_parameter)
        super().__init__(parameter)
        self.new_parameter = parameter

or in your case

class eg_experiment(experiment):
    def __init__(num_iter, bandit_list, epsilon):
        super().__init__(num_iter, bandit_list)  #Python3
        # super(experiment,self).__init__(num_iter, bandit_list) # Pythyon2.7
        self.epsilon = epsilon
rwhitt2049
  • 380
  • 4
  • 8
0

There's a saying: "If your class only has two methods, and one is __init__, use a function instead." Especially here, where there is no common implementation of the run method. You just have a bunch of independent functions with similar signatures.

def run_experiment_one(num_iter, bandit_list):
    ...

def run_experiment_two(num_iter, bandit_list):
    ...

def run_experiment_three(num_iter, bandit_list, epislon):
    ...
chepner
  • 497,756
  • 71
  • 530
  • 681