Как инициировать функцию при инициализации класса для установки атрибутов в дочернем классе?

У меня есть модель с именем Row ниже. Мне нужно создать несколько моделей на основе одной базовой модели.

class Row:
    def __init__(self, 
             date=None, 
             cost=None, 
             currency=None):
        self.date = date
        self.cost = cost
        self.currency = currency

    def to_dict(self):
        return {
            "date": self.date,
            "cost": self.cost,
            "currency": self.currency
    }

    def __repr__(self):
        return "%s(Date: %s, Cost: %s, Currency: %s, ConversionRt: %s, CampaignId: %s)" % (self.__class__.__name__, 
                  self.date, self.cost, \
                  self.currency)

Пример дочернего класса будет выглядеть следующим образом:

class ChildRow(Row):
    def __init__(self, row, metrics):
        super().__init__(
            self.assign_rows(row, metrics)
        )

    def assign_rows(self,
                    row,
                    metrics):
        self.date = metrics['date']
        self.cost = metrics['cost']['amount']
        self.currency = row['localSpend']['currency']

Дочерний класс должен будет принимать несколько словарей ответов json, а также извлекать и назначать определенные параметры для каждого атрибута. По какой-то причине я не могу заставить это работать со следующими полезными нагрузками. Атрибуты просто не будут установлены по какой-то причине.

row = {'localSpend': {'currency': 'USD'}}
metrics = {'date': '20190401', 'cost': {'amount': 290.5999}}

Если я создам экземпляр ChildRow, я ожидаю, что он автоматически запустит assign_rows и установит данные в атрибуты. Любые идеи, что я делаю неправильно здесь? Дочерний класс возвращает None для всех атрибутов. Я также открыт для других или лучших идей моделирования. Спасибо

Можете ли вы показать, как вы используете row и metrics для создания экземпляра класса, также ваше определение __repr__ неверно

Devesh Kumar Singh 19.06.2019 22:04
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

У тебя странное понимание того, как здесь все работает. Ваш код делает следующее:

  • вызов assign_rows, который присваивает значения атрибутам экземпляра
  • (неявно) возвращает None из этого метода
  • передает это возвращаемое значение, т.е. None, в метод родительского класса __init__.
  • этот метод принимает это значение None как значение параметра date. Два других параметра используют свои значения по умолчанию, которые также равны None.
  • Все три значения None назначаются атрибутам экземпляра, переопределяя значения, которые вы ранее установили в assign_rows.

Таким образом, значения являются устанавливаются, но затем перезаписываются значением None.

Я не знаю, почему вы думаете, что вам нужно передать результат функции в супервызов. Значения установлены; вы можете пропустить супер вообще. Просто сделайте это:

class ChildRow(Row):
    def __init__(self, row, metrics):
        self.assign_rows(row, metrics)

Или, как вариант, перенести логику из assign_rows прямо в __init__ и снова пропустить вызов super:

class ChildRow(Row):
    def __init__(self, row, metrics):
        self.date = metrics['date']
        self.cost = metrics['cost']['amount']
        self.currency = row['localSpend']['currency']

Я не уверен, с какой целью вы добавили функцию assign_rows, но обратите внимание, что вы вызываете конструктор базового класса ПОСЛЕ с возвращаемым значением из assign_rows (которое всегда None, поскольку он ничего не возвращает), поэтому все ваши значения затем перезаписываются с помощью значения по умолчанию.

Это будет работать так (и это чище):

class ChildRow(Row):
    def __init__(self, row, metrics):
        super().__init__(
            date=metrics['date']
            cost=metrics['cost']['amount']
            currency=row['localSpend']['currency']
        )

Другие вопросы по теме