Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/331.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_Constructor_Immutability_Software Design - Fatal编程技术网

Python 修改工厂函数中的不可变对象

Python 修改工厂函数中的不可变对象,python,design-patterns,constructor,immutability,software-design,Python,Design Patterns,Constructor,Immutability,Software Design,是否有描述以下设置的设计模式?该设计是否存在任何重大问题 类Widget实例可以通过“哑”构造函数Widget.\uuu init\uuu(),或通过“智能”工厂方法工作台来构建。升级\u Widget(): 小部件是不可变的,因为我不能在它们完全初始化之后修改它们的实例(很多代码都依赖于这个不变量)。但是我发现在初始化小部件时修改它们非常方便,并且使代码更干净 我主要关心的是在不同的类中修改“不可变”的小部件。如果它只是在升级\u widget中,我可能会接受它,因为它不会修改传递给它的wid

是否有描述以下设置的设计模式?该设计是否存在任何重大问题

Widget
实例可以通过“哑”构造函数
Widget.\uuu init\uuu()
,或通过“智能”工厂方法
工作台来构建。升级\u Widget()

小部件是不可变的,因为我不能在它们完全初始化之后修改它们的实例(很多代码都依赖于这个不变量)。但是我发现在初始化小部件时修改它们非常方便,并且使代码更干净


我主要关心的是在不同的类中修改“不可变”的小部件。如果它只是在
升级\u widget
中,我可能会接受它,因为它不会修改传递给它的widget。但是该方法依赖于其他
Workbench
方法(
reareat\u widget
),这些方法修改它作为参数接收的widget。我感觉我正在失去对这个“不可变”实例的实际修改位置的控制——有人可能会意外地调用
重新排列\u widget
,而该widget已经完全初始化,这将导致一场灾难。

您现在如何强制实现该widget的不可变性

如果将“锁定”属性添加到小部件中,并包装setattr以检查该属性,该怎么办

class Widget(object):
    __locked = False
    def __init__(self,a,b,c,locked=True):
        ...
        self.__locked = locked

    def lock(self):
        self.__locked = True

    def is_locked(self):
        return self.__locked

    def __setattr___(self,*args,**kw):
        if self.__locked:
            raise Exception('immutable') # define your own rather than use Exception
        return super(Widget).__setattr__(self,*args,**kw)
然后在工厂里:

class Workbench(object):
    def upgrade_widget(self,widget,upgrade_info):
        widget = Widget(widget.a,widget.b,...,locked=False)
        self.rearrange_widget(widget, blah)
        widget.c = 1337
        widget.lock()
        return widget
在一般情况下,您可以非常肯定,一旦类被锁定,它就不会发生任何有趣的事情。任何关心小部件不变性的方法都应该检查该小部件的is_locked()。例如,在做任何事情之前,重排小部件应该检查小部件是否也已解锁

尽管存在恶意篡改实例的情况,但无论如何都可能发生这种情况。它也不能防止属性被自己的方法改变

请注意,我上面编写的代码(伪python)没有经过测试,但希望它说明了如何处理主要问题的一般思路


哦,我不确定这个模式是否有一个特别的名字。

@chees:一个更简洁的方法是修改
\uuuuuu dict\uuuuuu
中的
\uu init\uuuuuuuu
并使
\uuuuu setattr\uuuuuuuuuuuuu
总是引发异常(顺便说一句,
引发异常不是一个好主意,只是一般性的):


在Workbench中以同样的方式修改它(即使用
\uuuu dict\uuuu
)会不断提醒您正在做一些不应该做的事情。

除了这个问题:在Python2中,始终从“object”继承类-否则您可能会缺少特性,难以诊断错误行为,因为不从对象继承的类是老式类。对不起,应该说它是Python 3…顺便说一句,每当我这样做时,我通常在它自己的类中实现锁定并从它继承。。。类似于类可锁定(对象):。。。类小部件(可锁定):…同意不引发异常-为了方便起见,您需要实现自己的异常(我将对此发表评论)。我确实发现,如果你不得不大量使用dict访问属性,那么通过dict访问属性会有点拖拉,尽管这确实是一个很好的抑制因素……确切地说。有时,您希望API成为一个拖拽,以提醒您不应该真正这样做,就像从类外部访问一个双下划线的私有属性一样。
class Workbench(object):
    def upgrade_widget(self,widget,upgrade_info):
        widget = Widget(widget.a,widget.b,...,locked=False)
        self.rearrange_widget(widget, blah)
        widget.c = 1337
        widget.lock()
        return widget
class Widget:
    def __init__(self, args):
        self.__dict__['args'] = args

    def __setattr__(self, name, value):
        raise TypeError