Getter with side effect

蹲街弑〆低调 提交于 2019-12-12 07:25:32

问题


I create a class whose objects are initialized with a bunch of XML code. The class has the ability to extract various parameters out of that XML and to cache them inside the object state variables. The potential amount of these parameters is large and most probably, the user will not need most of them. That is why I have decided to perform a "lazy" initialization.

In the following test case such a parameter is title. When the user tries to access it for the first time, the getter function parses the XML, properly initializes the state variable and return its value:

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         

This looks nice and works fine for me. However, I am disturbed a little bit by the fact that the getter function is actually a "setter" one in the sense that it has a very significant side effect on the object. Is this a legitimate concern? If so, how should I address it?


回答1:


While the getter certainly performs a side-effect, that's not traditionally what one would consider a bad side-effect. Since the getter always returns the same thing (barring any intervening changes in state), it has no user-visible side-effects. This is a typical use for properties, so there's nothing to be concerned about.




回答2:


This design pattern is called Lazy initialization and it has legitimate use.




回答3:


Quite some years later but well: while lazy initialization is fine in itself, I would definitly not postpone xml parsing etc until someone accesses the object's title. Computed attributes are supposed to behave like plain attributes, and a plain attribute access will never raise (assuming the attribute exists of course).

FWIW I had a very similar case in some project I took over, with xml parsing errors happening at the most unexpected places, due to the previous developper using properties the very same way as in the OP example, and had to fix it by putting the parsing and validation part at instanciation time.

So, use properties for lazy initialization only if and when you know the first access will never ever raise. Actually, never use a property for anything that might raise (at least when getting - setting is a different situation). Else, dont use a property, make the getter an explicit method and clearly document it might raise this or that.

NB : using a property to cache something is not the problem here, this by itself is fine.



来源:https://stackoverflow.com/questions/4739597/getter-with-side-effect

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!