首页 > 解决方案 > 如何创建具有动态子属性的@property?

问题描述

我有一门课,Tariff有数量和一些价格:

class Tariff():
    quantity = 0
    item_1_price = 250
    item_1_selected = False
    item_2_price = 350
    item_2_selected = False
    item_3_price = 165
    item_3_selected = False

    @property
    def total(self):
        return sum([
            self.item_1_price * self.item_1_selected,
            self.item_2_price * self.item_2_selected,
            self.item_3_price * self.item_3_selected,
            ]) * self.quantity

我可以这样使用它:

purchase = Tariff()
purchase.quantity = 2
purchase.item_1_selected = True
purchase.item_2_selected = True
print(purchase.total)
> 1200

我想要一个可以告诉我单个项目总数的函数。例如:

print(purchase.totals.item_1)
> 500

解决这个问题的最佳方法是什么?这可能/容易吗?

标签: python

解决方案


一个直接的方法是:

@property
def total(self):
    return dict(
        sum=sum([ self.item_1_price * self.item_1_selected,
                  self.item_2_price * self.item_2_selected,
                  self.item_3_price * self.item_3_selected,
                ]) * self.quantity,
        item_1=item_1_price,
        item_2=item_2_price,
        item_3=item_3_price)

然后这将返回一个包含所有想要的信息的字典。但是,要访问 dict 中的元素,您需要使用索引语法:

print(purchase.totals['item_1'])
> 500

如果你能忍受这个,这就是我想要的。

如果您需要拥有属性,则需要创建一个包含这些属性的对象(或至少伪造它们)。看看collections.namedtuple这个:

Totals = collections.namedtuple('total',
                                ['item_1', 'item_2', 'item_3', 'sum'])
return Totals(sum=sum([ self.item_1_price * self.item_1_selected,
                        self.item_2_price * self.item_2_selected,
                        self.item_3_price * self.item_3_selected,
                     ]) * self.quantity,
              item_1=item_1_price,
              item_2=item_2_price,
              item_3=item_3_price)

然后你可以使用:

print(purchase.totals.item_1)
> 500

推荐阅读