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}}?可能吗?或者甚至方法计算对象的创建位置?
答案 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模板中),但每次都不会计算数量 - 它会使用存储的数量。