Python-Borg多重继承和共享

2024-04-27 05:47:32 发布

您现在位置:Python中文网/ 问答频道 /正文

我在一个有趣的项目中遇到了这个问题,在这个项目中,我必须告诉一个类在指定的开始和结束时间(以及间隔of c)的特定时间段内执行一个操作。在

为了便于讨论,考虑类A(拥有我调用的API的类)必须调用类B(它调用类C,反过来调用类D)和E(反过来调用类F和类G)。在

A->;B->;C->;D

A->;E->;G

现在B、C、E类需要时间的上下文。我目前已经设置了它,以便类A将上下文传递给类B和E,然后它们根据需要依次传递上下文。在

我正试图找出解决这个需求的最佳方法,而不需要传递上下文,尽管我很讨厌,但我正在考虑使用Highlander(或Singleton)或Borg模式(Monostate的变体)。我只是想知道我对这些模式有什么选择。在

选项1

使用传统伯格呼吸困难综合征,例如:

class Borg:
    __shared_state = {}
    def __init__(self):
        self.__dict__ = self.__shared_state

我可以简单地在任何地方实例化这个类,并且可以访问我想要的全局状态。在

选项2

单态的另一个变体:

^{pr2}$

从理论上讲,我可以简单地通过以下方式进行扩展:

class X(InheritableBorg):
    pass

为了扩展我只想:

class NewInheritableBorg(InheritableBorg):
    __time = (0, 0, 'd')

从理论上讲,我可以利用多重继承,然后可以一次性访问多个borg,例如:

class X(InheritableBorg1, InheritableBorg2):
    pass

我甚至可以有选择地覆盖那些东西。在

选项3

如果可能,请使用包装的嵌套函数作为类装饰器/包装器。但是,我只能使用一次,并且需要传递函数句柄。这是基于代理/委托的混合思想。在

这在我的头脑中不是具体的,但本质上类似于:

def timer(time)
    def class_wrapper(class_to_wrap):

        class Wrapper(class_to_wrap):
            def __init__(self, *a, **kw):
               super().__init__(*a, **kw)
            def get_time(self):
               return time
        return Wrapper
    return class_wrapper

@timer(time)
class A_that_needs_time_information:
    pass

I think that might work... BUT I still need to pass the function handle.

摘要

所有这些都是可能的解决方案,我倾向于多重继承的Borg模式(尽管类包装很酷)。在

  1. 常规的Borg模式必须被实例化很多次,这似乎是太多的开销仅仅存储一组值。

  2. Borg mixin的实例化次数与类的实例化次数相同。我看不出测试会有多困难。

  3. 包装器是超通用的,相对容易测试。理论上,因为它是一个函数闭包,所以我应该可以改变它,但实际上它变成了一个单例函数(这看起来太复杂了,在这种情况下,我不妨使用常规的singleton模式)。另外,传递函数句柄也会破坏目的。

除了这三种方法,还有其他方法吗?有更好的方法吗(博格人似乎不容易测试,因为没有DI)?有什么缺点我似乎错过了?在

或者我可以坚持我现在所拥有的。。。按要求消磨时间。它满足松耦合要求和DI最佳实践。。。但这太麻烦了。一定有更好的办法!在


Tags: 实例方法函数gtselftimeinitdef
1条回答
网友
1楼 · 发布于 2024-04-27 05:47:32

一般来说,尽量保持简单。你在考虑一个相对简单的问题非常复杂的解决方案。在

根据您提供的信息,您似乎可以将执行操作的请求包装在一个对象中,该对象还包含上下文。然后在不同的类之间传递一个对象。例如:

class OperationRequestContext:
    def __init__(self, start_time, end_time):
        self.start_time = start_time
        self.end_time = end_time

class OperationRequest:
    def __init__(self, operation, context):
        self.operation = operation
        self.context = context

如果有其他的要求可以证明需要考虑更复杂的解决方案,您应该指定它们。在

相关问题 更多 >