吸气剂有副作用

时间:2011-01-19 19:16:12

标签: python design-patterns for-loop getter-setter side-effects

我创建了一个用其初始化对象的类 一堆XML代码。该类能够从该XML中提取各种参数,并将它们缓存在对象状态变量中。这些参数的潜在数量很大,很可能用户不需要大部分参数。这就是我决定执行“懒惰”初始化的原因。

在以下测试用例中,此参数为title。当用户第一次尝试访问它时,getter函数会解析XML,正确初始化状态变量并返回其值:

class MyClass(object):     
    def __init__(self, xml=None):
        self.xml  = xml
        self.title = None

    def get_title(self):
        if self.__title is None:
            self.__title = self.__title_from_xml()
        return self.__title

    def set_title(self, value):
        self.__title = value

    title = property(get_title, set_title, None, "Citation title")

    def __title_from_xml(self):
        #parse the XML and return the title
        return title         

这看起来不错,对我来说很好。然而,由于getter函数实际上是一个“setter”,因为它对对象有非常显着的副作用,我对此感到不安。这是一个合理的担忧吗?如果是这样,我该如何解决?

3 个答案:

答案 0 :(得分:14)

此设计模式称为Lazy initialization,它具有合法用途。

答案 1 :(得分:4)

虽然吸气剂肯定会产生副作用,但传统上并不是人们认为会产生副作用。由于getter总是返回相同的东西(除非状态中有任何干预变化),它没有用户可见的副作用。这是属性的典型用法,所以没有什么值得关注的。

答案 2 :(得分:0)

几年之后但很好:虽然懒惰的初始化本身很好,但我肯定不会推迟xml解析等,直到有人访问对象title。计算属性应该像普通属性一样,并且普通属性访问永远不会引发(假设属性当然存在)。

FWIW我在一些项目中遇到了一个非常类似的情况,xml解析错误发生在最意想不到的地方,因为之前的开发人员使用的属性与OP示例中的方式相同,并且必须修复它通过将解析和验证部分放在实例化时间。

因此,只有当知道时,才会使用属性进行延迟初始化永远不会引发。实际上,永远不要将属性用于任何可能引发的事情(至少在获取 - 设置是不同的情况时)。否则,不要使用属性,使getter成为一个明确的方法,并清楚地记录它可能引发这个或那个。

注意:使用属性缓存某些东西不是问题,这本身就没问题。