python:围绕第三方类编写包装器

时间:2011-01-19 01:54:04

标签: python design-patterns interface wrapper

我需要来自第三方模块m的X类的一些功能。我可以直接使用m.X,但是我可能需要在将来用另一个类n.Y替换m.X(例如,如果我发现更好的实现)。

在这种情况下,我想避免更改其余的代码。

现在,我希望m.X的完整界面(包括初始化)不变地传递。我为m.X写了一个包装W,如下所示:

class W(m.X):
    def __init__(self, *args):
        super().__init__(*args)

将来,如果需要,我打算将上述内容重写为:

class W(n.Y):
    def __init__(self, *args):
        super().__init__(*args)
    # override instance methods of n.Y that don't share the semantics with m.X
    # for example, in case f1 is hard to replicate in n.Y:
    # def f1(self, *args):
    #     print("this method is no longer available")
    #     raise MyDeprecatedMethod()
    # for example, in case f2 needs to be recalculated
    # def f2(self, *args):
          # do the calculations required to keep W.f2 unchanged 

我当前的m.X包装是否可以接受?是否存在问题,或者是否存在n.Y的计划包装?

3 个答案:

答案 0 :(得分:3)

你可以简单地使用

class W(m.X):
    pass

默认继承m.X.__init__()

答案 1 :(得分:2)

最简单的方法是写:

W = m.X

实际上Python中的所有东西都是一流的对象 - 包括类型。一个类几乎与任何其他变量无法区分,例如:

def W(*args, **kwargs):
    return m.X(*args, **kwargs)

可以实例化m.X的实例,同时显示W是它的实际名称。 (请注意,使用此方法isinstance将无法正常工作 - 与第一个示例一起使用。)

在某些情况下,使用赋值可能无法很好地与IDE配合使用。在这种情况下:

class W(m.X): pass

也会产生相同的结果,但W的实例仅增加了m.X的实例,因为W是一个子类:使用W=m.X; W(args)将创建m.X

的实例

答案 2 :(得分:0)

这取决于你使用的方法中m.X和n.Y的差异,但它可能就像

一样简单
try:
    import n.Y as foo
except ImportError:
    import m.X as foo

class W(foo):
    pass

因此,您的代码会自动反映新模块,可能会最大限度地减少您在整个代码库中所做的更改。