Наследование от _ <type>в Python - PullRequest
       39

Наследование от _ <type>в Python

0 голосов
/ 02 сентября 2011

Редактировать: Была некоторая путаница, но я хочу задать общий вопрос об объектно-ориентированном дизайне в Python.

Рассмотрим класс, который позволяет отображать значения данных на счет или частоту:

class DataMap(dict):
    pass

Теперь рассмотрим подкласс, который позволяет вам строить гистограмму из списка данных:

class Histogram(DataMap):
    def __init__(self, list_of_values):
        # 1. Put appropriate super(...) call here if necessary
        # 2. Build the map of values to counts in self
        pass

Теперь рассмотрим класс, который позволяет вам создать сглаженную таблицу вероятностей, а не Histogram.

class ProbabilityMass(DataMap):
    pass

Каков лучший способ разрешить построение ProbabilityMass из Histogram или списка значений?

Я "вырос", программируя на C ++, и в этом случае я бы использовал перегруженный конструктор. В Python я думал сделать это с:

  • Конструктор принимает несколько аргументов (все, кроме одного, должны == Нет)
  • Я определяю методы from_Histogram и from_list

Во втором случае (который, я считаю, лучше), как лучше всего разрешить методу from_list использовать общий код из конструктора Histogram? Таблица ProbabilityMass практически идентична таблице Histogram, но она масштабируется таким образом, чтобы сумма всех значений составляла 1,0.

Если вы столкнулись с подобной проблемой, пожалуйста, поделитесь своим опытом!

1 Ответ

3 голосов
/ 02 сентября 2011

Для начала, если вы думаете, что хотите @staticmethod, вы почти всегда этого не делаете. Либо функция не является частью класса, и в этом случае она должна быть просто свободной функцией, либо она является частью класса, но не привязана к экземпляру, и она должна быть @classmethod. Ваш названный конструктор является хорошим кандидатом на @classmethod.

Также обратите внимание, что вы должны вызывать A.__init__ из B через super(), в противном случае множественное наследование может вас сильно укусить.

class A:
    def __init__(self, data):
        self.values_to_counts = {}
        for val in data:
            if val in self.values_to_counts:
                self.values_to_counts[val] += 1
            else:
                self.values_to_counts[val] = 1
    @classmethod
    def from_values_to_counts(cls, values_to_counts):
        self = cls([])
        self.values_to_counts = values_to_counts
        return self

class B(A):
    def __init__(self, data, parameter):
        super(B, self).__init__(data)
        self.parameter = parameter
    def print_parameter(self):
        print self.parameter

В этом случае вам не нужен B.from_values_to_counts, он наследуется от A, и он вернет экземпляр B, так как он был назван.

Если вам нужно выполнить более сложную инициализацию в B, вы можете, используя super(), что выглядит очень похоже на то, как если бы вы использовали его с экземплярами. в конце концов, classmethod на самом деле не является чем-то более сложным, чем instancemethod, где атрибут im_self назначен самому классу.

class A:
    def __init__(self, data):
        self.values_to_counts = {}
        for val in data:
            if val in self.values_to_counts:
                self.values_to_counts[val] += 1
            else:
                self.values_to_counts[val] = 1
    @classmethod
    def from_values_to_counts(cls, values_to_counts):
        self = cls([])
        self.values_to_counts = values_to_counts
        return self

class B(A):
    def __init__(self, data, parameter):
        super(B, self).__init__(data)
        self.parameter = parameter
    def print_parameter(self):
        print self.parameter
    @classmethod
    def from_values_to_counts(cls, values_to_counts):
        self = super(B, cls).from_values_to_counts(values_to_counts)
        do_more_initialization(self)
        return self
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...