【问题标题】:python: writing a wrapper around a third-party classpython:围绕第三方类编写包装器
【发布时间】:2011-06-11 11:44:21
【问题描述】:

我需要来自第三方模块 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 的计划包装器有问题吗?

【问题讨论】:

  • 对我来说看起来不错(至少,我是这样做的)
  • 您真正需要多少包装?如果唯一的问题是保护其余代码免受潜在的命名更改影响,那么只需 W = m.X 就足够了,不是吗?

标签: python design-patterns interface wrapper


【解决方案1】:

你可以简单地使用

class W(m.X):
    pass

默认继承m.X.__init__()

【讨论】:

    【解决方案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 的实例。

    【讨论】:

    • 如果 OP 想要覆盖更改的函数,他们可以执行 def myFun(self, *args): doSomething()W.f1 = myFun; W.f2 = myFun 等。
    • @Fantasizer 这会起作用,但也适用于m.X。重写函数最好通过创建一个新类并仅重写所需的方法来完成(除非它发生变化,否则无需执行 __init__)。
    【解决方案3】:

    这取决于您使用的方法中 m.X 和 n.Y 的不同程度,但它可能很简单

    try:
        import n.Y as foo
    except ImportError:
        import m.X as foo
    
    class W(foo):
        pass
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多