Python3:如何重新设计嵌套的类层次结构,以实现更好的序列化和/或促进更好的模型/视图解耦

时间:2018-10-13 11:01:14

标签: python class design-patterns serialization yaml

我和我的一个朋友,我们一直在为光学射线追踪器开发代码。该光线跟踪器由对象层次结构组成,其中某些类包含变量,这些变量被实现为或多或少复杂的有状态对象。这些类还可能包含其他类似类的实例,这些类也包含那些变量对象或其他类实例。

首先,我们将提供一个“最小”的工作示例:

class OptVar:
    """
    Complicated stateful variable
    """
    def __init__(self, **kwargs):
        self.parameters = kwargs


class OptVarContainer:
    """
    Class which contains several OptVar objects and nested OptVarContainer
    classes. Is responsible for OptVar management of its sub-OptVarContainers
    with their respective OptVar objects.
    """
    def __init__(self, **kwargs):
        for (key, value_dict) in kwargs.items():
            setattr(self, key, OptVar(**value_dict))


class C(OptVarContainer):
    """
    Specific implementation of class OptVarContainer
    """
    def __init__(self):
        super(C, self).__init__(
                **{"my_c_a": {"c1": 1, "c2": 2},
                   "my_c_b": {"c3": 3, "c4": 4}})


class B(OptVarContainer):
    """
    Specific implementation of class OptVarContainer
    """
    def __init__(self):
        super(B, self).__init__(**{"b": {"1": 1, "2": 2}})
        self.c_obj = C()


class A(OptVarContainer):
    """
    Specific implementation of class OptVarContainer
    """
    def __init__(self):
        super(A, self).__init__(
                **{"a1": {"1": 1, "2": 2},
                   "a2": {"a": "a", "b": "b"}})
        self.b_obj = B()


def main():
    # creating OptVarContainer with some nested OptVarContainers.
    my_a_obj = A()
    # It is intended behaviour to access the OptVar objects via
    # scoping within the class hierarchy.
    print(my_a_obj.b_obj.b.parameters)
    my_a_obj.b_obj.b.parameters["2"] = 3
    print(my_a_obj.b_obj.b.parameters)
    print(my_a_obj.b_obj.c_obj.my_c_a.parameters["c1"])
    my_a_obj.b_obj.c_obj.my_c_a.parameters["c1"] = 6
    print(my_a_obj.b_obj.c_obj.my_c_a.parameters)
    # Two major problems:
    # a) Serialization (with compatibility between different versions)
    # b) Access to all OptVar objects at once


if __name__ == "__main__":
    main()

因此,最终要优化的光学系统(后来)是OptVarContainer类型,并以分层方式包含多个对象。

有两个主要问题:

  • 对象的序列化,无需过多的管理工作和版本稳定性,即可与用户界面交互或稍后进行重构
  • 轻松访问和管理以某种方式分布在对象层次结构中的变量对象(以便以后集成到用户界面中)

为了进行优化,以后会收集OptVars,并使用它们的状态将其放入numpy数组中并将其移交给优化器。

对象(A,B,C)可能以递归方式连接,因此序列化和对OptVar对象的轻松访问非常复杂。对于a)部分,代码中没有解决方案。目前,b)部分的解决方案是遍历从my_a_obj到b_obj到c_obj的对象层次结构,收集所有OptVar对象(防止使用id列表加倍)并返回一个dict。这可行,但是对我们来说这只是一个临时解决方案,而且非常难看。

总体目标是仅使用要传递的命令来使序列化和与GUI的后续交互变得非常容易。 (是否有更好的选择来解决这两个任务?)这也将简化OptVarContainers和Optimizer之间的交互,因为接口仅是命令。

我们对a)做了一些研究,并发现了pickle,JSON,YAML用于序列化。我们还使用jsonpickle进行了一些测试,该测试工作时不会遇到递归对象层次结构的问题。由于jsonpickle自动进行所有序列化,因此我们不必在意。对我们来说,主要缺点是,如果基础对象发生更改,则无法重建jsonpickle对象,因此没有版本稳定性。此外,编写一个串行器后端而不淹没管理代码似乎相当复杂。因此,我们的决定是在一天结束时准备一个非常简单的YAML“字典”,并且类层次结构中的每个对象都应根据请求提供自己的字典(在理想情况下,该字典也可以用于重建对象)。问题是:如何以一种非常通用的方式实现这一目标?纪念品设计模式是否适合于此?可以在上面给出的A,B,C上下文中使用这些类,它们只是相似而不是相等,并且以这种复杂的方式互连吗?

我们还对b)进行了一些思考,并且我们认为某种OptVars池将很不错,因为该池易于遍历并且可以包含复杂的有状态变量对象。然后,在A,B,C类中,我们将仅提供到OptVars的一些“链接”。但是,这种方法存在两个主要问题:

  • 如何实现这样的对象池?我读到了关于此设计模式的信息,该设计模式是作为单例实现的,但是在我们的情况下,单例可能不是最好的选择。这是因为一次一次应该有多个池(可能是针对不同版本的类层次结构,或者是加载和保存池)。它也不是唯一的数据接收器,也没有单一的全局状态。
  • 如何管理此类池以及如何在Python中实现它?我们不想有一个全局变量,但是我们也不希望每次创建A,B,C对象时都提供池。是否有更好的可能性将OptVars自动放入给定池中?
  • 应如何实现池OptVar与A,B,C OptVar之间的链接?代理设计模式?还有其他设计模式吗?

很抱歉,如果问题不适用于stackexchange或格式相当混乱。我知道存在特定且独特的解决方案是没有问题的,但是对我们来说,有必要对此提供一些意见。

0 个答案:

没有答案