惯用蟒蛇 - 属性还是方法?

时间:2013-07-02 15:07:43

标签: python django

我有一个django模型类,它将状态维护为一个简单的属性。我在类中添加了几个辅助属性来访问聚合状态 - 例如如果状态是is_live等中的任何一个,则['closed', 'expired', 'deleted']返回false。

因此,我的模型有一个is_属性集合,可以对对象的内部属性进行非常简单的查找。

我现在想要添加一个新属性is_complete - 它在语义上与所有其他属性相同 - 对对象状态进行布尔检查 - 但是,此检查涉及加载依赖(一个 - to-many)子对象,检查它们的状态并根据结果报告 - 即这个属性实际上做了一些(多个)数据库查询,并处理结果。

那么,建模作为属性(使用@property装饰器)是否仍然有效,或者我应该放弃装饰器并将其保留为方法?

使用属性的Pro是它在语义上与所有其他is_属性一致。

使用方法的专业是,它向其他开发人员表明这是一个具有更复杂实现的东西,因此应该谨慎使用(即不在for..循环内)。

from django.db import models

class MyModel(models.Model):

    state = CharField(default='new')

    @property
    def is_open(self):
        # this is a simple lookup, so makes sense as a property
        return self.state in ['new', 'open', 'sent']

    def is_complete(self):
        # this is a complex database activity, but semantically correct
        related_objects = self.do_complicated_database_lookup()
        return len(related_objects)==0

编辑:我最初来自.NET背景,其中杰夫阿特伍德精心定义了分裂

  

“如果有任何机会可以产生沙漏,那肯定应该是一种方法。”

编辑2:对问题进行轻微更新 - 将它作为一种名为is_complete的方法将是一个问题,以便混合属性和具有相似名称的方法 - 或者只是令人困惑? / p>

所以 - 它看起来像这样:

>>> m = MyModel()
>>> m.is_live
True
>>> m.is_complete()
False

1 个答案:

答案 0 :(得分:9)

可以这样做,特别是如果你将使用以下模式:

class SomeClass(models.Model):
    @property
    def is_complete(self):
        if not hasattr(self, '_is_complete'):
            related_objects = self.do_complicated_database_lookup()
            self._is_complete = len(related_objects) == 0
        return self._is_complete

请记住它"缓存"结果,所以首先执行计算,但后续使用现有结果。