如何在类初始化时启动函数以设置子类中的属性?

时间:2019-06-19 19:55:04

标签: python python-3.x

下面我有一个名为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。我也欢迎其他更好的建模想法。谢谢

2 个答案:

答案 0 :(得分:1)

您对这里的工作方式有一个奇怪的了解。您的代码将执行以下操作:

  • 调用assign_rows,它分配实例属性的值
  • (隐式)从该方法返回None
  • 将返回值(即None)传递到父类__init__方法中。
  • 该方法将None值作为date参数的值。其他两个参数使用其默认值,也均为“无”。
  • 所有三个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']

答案 1 :(得分:1)

我不确定添加assign_rows函数的目的是什么,但是请注意,您正在使用assign_rows(始终为{{1 }},因为它什么也不返回),因此所有值都将被默认值覆盖。

它会像这样工作(而且更干净):

None