Как использовать super для наследования от двух отдельных классов с разными аргументами конструктора? - PullRequest
1 голос
/ 24 мая 2019

Я пытаюсь лучше понять множественное наследование и подклассы.Мне известно, что порядок разрешения методов (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?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...