【问题标题】:python best practices - classes are very similar, but constructor is differentpython最佳实践——类非常相似,但构造函数不同
【发布时间】:2017-11-04 02:08:20
【问题描述】:

我创建了四个类:experiment, experiment_type1, experiment_type2 and experiment_type3

experiment 是一个抽象类,它不能被实例化。它有 2 个方法,__init__(self)run(self) 其中run(self) 是抽象的。

experiment_type1experiment_type2 来自实验。它们从experiment 继承__init__(self)(因此它们共享相同的构造函数),但它们实现run(self) 的方式彼此不同。

我的问题是 experiment_type3 类。它也只有run(self) 方法,实现方式与experiment_type1experiment_type2 不同,但它的构造函数需要一个额外的参数。它的构造函数是__init__(self, parameter)

理想情况下,我希望 experiment_type3 派生自 experiment。但是有一个构造函数不匹配。处理这个问题的最佳方法是什么?本例使用python编程。

编辑: 这是experiment 和experiment_type3 的代码。如您所见,它依赖于不存在的 self.epsilon。

将 numpy 导入为 np 从 abc 导入 ABC,抽象方法 从强盗导入强盗

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])

【问题讨论】:

  • 您应该在帖子中包含完整的来源,这样更有可能获得良好的回应。见stackoverflow.com/q/18006310/489590我认为是相关的。
  • 重写构造函数?
  • 我不确定这是最好的解决方案。这是可能的,但我想做的就是添加一个 self.parameter = 参数。不确定是否保证整个构造函数的代码重复
  • 然后在被覆盖的构造函数中调用超类构造函数,然后设置你的属性?

标签: python class oop inheritance


【解决方案1】:

正如 cmets 所指出的,在父类的 __init__ 上使用 super() 应该可以满足您的需求。

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

或者在你的情况下

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

【讨论】:

    【解决方案2】:

    有句话说:“如果你的类只有两个方法,一个是__init__,那就用函数代替。”尤其是在这里,没有run 方法的通用实现。你只是有一堆具有相似签名的独立函数。

    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):
        ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-17
      • 1970-01-01
      • 2021-02-13
      • 2017-09-13
      • 2022-11-04
      • 1970-01-01
      相关资源
      最近更新 更多