属性和类方法有什么区别?

时间:2015-04-30 13:07:14

标签: python django django-models

property和班级method之间有什么区别?据我所知,属性是在创建对象时计算的。当我调用它时,方法会进行计算吗?或者那有什么不同吗? 例如,我property中有一个class Product()

@property
    def total_ammount_in_store(self):
        consignments = self.product.package.consignments
        total_ammount = 0
        for consignment in consignments:
            total_ammount += consignment.package_ammount

当我渲染某个页面时,我会传递一些产品,例如:{'products':Product.objects.filter(expiration_data < datetime.now()) 每次获得total_ammount_in_store的实例时,我都不需要计算Product。如果我在模板中调用它时需要计算它,该怎么办:{{product.total_ammount_in_store}}?可能吗?或者甚至方法计算对象的创建位置?

2 个答案:

答案 0 :(得分:3)

每次访问product.total_ammount_in_store时都会调用该属性,而不是在创建产品时调用。

因此,在模板中加入{{ product.total_ammount_in_store }}会做正确的事。

通过使用属性装饰器,如果它是实例方法,则可以访问product.total_ammount_in_store而不是product.total_ammount_in_store()。在Django模板语言中,这种差异并不那么明显,因为Django会在模板中自动调用该方法。

不要将实例方法与class method混淆,这是完全不同的。类方法属于您的类Product,而不是单个实例product。您无权访问实例变量,例如当你调用类方法时self.package

答案 1 :(得分:1)

@property装饰器可用于为您的类实例变量实现一个getter(在您的情况下,它将是self.total_ammount_in_store)。每次调用some_product.total_ammount_in_store时,都会执行修饰后的方法。仅在创建新对象时执行它是没有意义的 - 您希望在商店中获得当前金额,不是吗? 更多关于@property的阅读是在Python文档中(它是Python的构造,而不是Django的):

https://docs.python.org/2/library/functions.html#property

至于课堂方法,它们完全不同。顾名思义,它们与类有关,而非实例。因此,不需要实例来调用类方法,也不能在类方法中使用任何实例变量(因为它们与特定实例绑定)。

到你问题的Django相关部分......

如果在模板中包含{{ some_product.total_ammount_in_store }},则每次显示页面时,商店中的总金额都会从some_product实例中获取。这意味着调用了装饰的total_ammount_in_store getter。

例如,如果商品中的总金额在产品生命周期内未更改,则可以使用__init__方法计算金额,然后仅返回该值。如果总金额可以更改,您也可以这样做,但您需要确保每次更改金额时重新计算金额 - 例如通过调用方法。像这样:

class Product(object):
    def __init__(self):
        # ...
        # other initialization
        # ...
        self.recalculate_amount()

    def recalculate_amount(self):
        consignments = self.product.package.consignments
        self._total_amount = 0
        for consignment in consignments:
            self._total_amount += consignment.package_amount

    @property
    def total_amount(self):
        """Get the current total amount in store."""
        return self._total_amount

然后每次调用some_product.total_ammount_in_store时都会调用getter(例如在你的Django模板中),但每次都不会计算数量 - 它会使用存储的数量。