python:为第三方类编写包装器
我需要一个第三方模块m里面的类X的一些功能。我可以直接使用m.X,但将来我可能需要把m.X换成另一个类n.Y(比如,如果我发现了更好的实现方式)。
我希望在这种情况下,其他代码不需要做任何修改。
现在,我想要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
这要看你用的 m.X 和 n.Y 这两个方法有多大的不同,不过其实可以简单到像这样:
try:
import n.Y as foo
except ImportError:
import m.X as foo
class W(foo):
pass
这样你的代码就会自动反映出新的模块,可能会减少你在整个代码中需要做的修改。
3
你可以简单地使用
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
可能不会正常工作,但在第一个例子中是可以正常工作的。)
在某些情况下,使用赋值可能会和一些开发工具不太兼容。在这种情况下:
class W(m.X): pass
也会产生相同的结果,不过会多一些开销,因为W
的实例实际上只是m.X
的实例,因为W
是一个子类:使用W=m.X; W(args)
会创建一个m.X
的实例。