Я пытаюсь лучше понять множественное наследование и подклассы.Мне известно, что порядок разрешения методов (MRO) определяет порядок наследования классов.Я также читал, что super
является предпочтительным способом создания подклассов, вместо того, чтобы вручную запускать __init__
для каждого подкласса в целях удобства сопровождения и во избежание многократного запуска конструктора __init__
.Я читал другие связанные посты на этом сайте и документы по питону, но у меня возникают проблемы с пониманием того, как собрать все это вместе.
В качестве краткого примера рассмотрим следующие дочерние классы:
import numpy as np
class StudentIdentification():
def __init__(self, data, use_names, use_ids):
self.data = data
self.use_names = use_names
self.use_ids = use_ids
def check_use_inputs(self):
values = np.array([self.use_names, self.use_ids])
if np.all(values == True):
return True
elif np.all(values == False):
return False
else:
return None
class ScoreEvaluation():
def __init__(self, data, weights):
self.data = data
self.weights = weights
def get_weighted_score(self):
return np.sum(self.data * self.weights)
Я бы хотел, чтобы родительский класс GradeBook
ниже наследовал методы от обоих этих дочерних классов.Однако я знаю только, как использовать super
для наследования от первого ребенка, а не от остальных.
Для наследования от ScoreEvaluation
:
# class GradeBook(ScoreEvaluation, StudentIdentification):
#
# def __init__(self, data, weights, use_names, use_ids):
# """ """
# super().__init__(data, weights)
Для наследования от StudentIdentification
:
class GradeBook(StudentIdentification, ScoreEvaluation):
def __init__(self, data, weights, use_names, use_ids):
""" """
super().__init__(data, use_names, use_ids)
Затем можно безуспешно выполнить код как:
data = np.linspace(1, 10, 10)
weights = np.ones(data.size)
use_names = True
use_ids = False
GB = GradeBook(data, weights, use_names, use_ids)
boolean = GB.check_use_inputs()
nscore = GB.get_weighted_score()
print(boolean)
print(nscore)
Мне известно, что одним из обходных путей является реструктуризация кода таким образом, чтобы один дочерний объект наследовал от другого, даже если унаследованные методы не используются;таким образом, родитель GradeBook
наследует от ребенка и внука:
class StudentIdentification(ScoreEvaluation):
def __init__(self, data, weights, use_names, use_ids):
super().__init__(data, weights)
self.use_names = use_names
self.use_ids = use_ids
def check_use_inputs(self):
""" """
values = np.array([self.use_names, self.use_ids])
if np.all(values == True):
return True
elif np.all(values == False):
return False
else:
return None
class GradeBook(StudentIdentification):
def __init__(self, data, weights, use_names, use_ids):
""" """
super().__init__(data, weights, use_names, use_ids)
Хотя этот подход работает, я не думаю, что этот подход будет осуществим, поскольку код становится больше.Причина этого в том, что методы ScoreEvaluation
и StudentIdentification
полностью разделены;единственная общность между ними - аргумент конструктора data
.Так что, если кто-то хочет обновить соответствующий метод, это может быть трудно найти.Плюс как идея разделения кода по его логике / использованию;каждая функция / класс должна делать одну вещь (или мне сказали, что это хороший способ для Python).(Хотя data
не вызывается в StudentIdentification
, предположим, что фактический вариант использования запускает методы на data
.)
Я знаю, что могу использовать super
в первом классе, а затем вручную __init__
второй класс, но у меня сложилось впечатление, что это испортит MRO.В качестве альтернативы, я мог бы вручную __init__
оба класса (т.е. не запускать super
), но у меня (возможно, неправильно?) Сложилось впечатление, что super
является предпочтительным способом для множественного наследования для Python.Часть меня думает, что эти правила / предпочтения применимы к ситуации, отличной от моей, и используются только в том случае, если все унаследованные классы имеют одинаковые аргументы конструктора, но это тоже не совсем верно.
Я слишком придирчивили не пифонически, или есть более чистый способ, чтобы класс GradeBook
наследовал методы от StudentIdentification
и ScoreEvaluation
?