Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 副作用吸气剂_Python_Design Patterns_For Loop_Getter Setter_Side Effects - Fatal编程技术网

Python 副作用吸气剂

Python 副作用吸气剂,python,design-patterns,for-loop,getter-setter,side-effects,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

我创建了一个类,其对象用 一堆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”函数,从这个意义上说,它对对象有非常显著的副作用,这一事实让我有点不安。这是合理的担忧吗?如果是这样的话,我应该怎么称呼它?

< P>这种设计模式被称为是合法使用的。

< P>而吸气剂肯定会产生副作用,这不是传统上人们会考虑的不良副作用。由于getter总是返回相同的内容(除非状态发生任何中间更改),因此它没有用户可见的副作用。这是属性的一个典型用法,因此不需要担心。

很多年后,但很好:虽然延迟初始化本身很好,但我肯定不会推迟xml解析等,直到有人访问对象的
标题。计算属性的行为应该类似于普通属性,普通属性访问将永远不会出现(当然,假设该属性存在)

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

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


注意:在这里,使用属性缓存内容不是问题,这本身就可以。

无论问题的实际答案是什么,都不应该使用前导双下划线。他们开始弄虚作假,即许多潜在的痛苦和零收益。只需使用一个前导下划线。我不明白这是一个问题。次要的重构建议:不要在构造函数中初始化
self.\u title
,并用
not hasattr(self,“\u title”)
@delnan替换getter中的条件。@Sven Marnach:
not hasattr(自我,“头衔”)
对于惰性初始化来说是非常罕见的,并且比普通的属性查找和针对
None
的测试要慢。我不同意:在这种情况下,解析xml会引发异常,并且没有人期望属性访问会引发一些xml解析异常。在我接管的一个项目中,我有一个非常类似的案例d重写这部分代码,以便在实例化时进行解析,这样,如果xml以任何方式被破坏,则在稍后阶段不会发生异常。get属性不应引发任何异常。您是否希望普通属性访问引发任何异常(当然假设该属性存在)?计算属性应该和普通属性一样安全。cf我对接受答案的评论-惰性初始化很好,但这并不意味着应该允许属性访问引发任何问题。如果您的类使用惰性初始化,请确保这永远不会意味着任何异常,或者不要诱使用户认为他已被激活使用简单安全的属性访问并使getter成为显式方法,记录它可能引发这个或那个异常的事实。