如何编写适应成员类接口的容器/包装类?
我正在写一个类,这个类是用来包装另一个类的对象。我的目的是改变一些方法的行为,同时能够扩展它的其他接口。我没有使用继承,因为内部类的对象可能会消失,而外部类需要能够用一个新的对象替换它,而不需要摧毁自己。
所以我有:
class Inner():
def foo(): pass
def goo(): pass
class Outer():
self.inner = InnerFactory(innerType)
def foo():
try:
self.inner.foo()
except:
del self.inner
self.inner = InnerFactory(innerType)
self.inner.foo()
我的问题是,如何在不显式重写的情况下扩展goo,因为我可能还有很多其他我不知道的方法。
其实在看了一些下面的反馈后,我意识到我没有使用一个很棒的功能getattr。不过,我不太明白为什么下面的建议都看起来那么复杂。为什么不能简单点呢:
def __getattr__( self, name ):
if self.inner:
return getattr( self.inner, name )
else:
raise Exception( 'attribute %s not found' % name )
2 个回答
0
我的解决方案和@khachik的差不多,不过我加了一些方法缓存。
- 要小心,使用__ getattr__的时候很容易陷入无限循环。
- 如果需要的话,你可能还想加上线程锁。
代码没有经过测试,建议把它当作伪代码来看。
class Outer(object):
def __init__(self):
self.method_cache = {}
self.methods_to_override = ['foo', 'goo']
def __getattr__(self, method_name):
if method_name in self.methods_to_override:
if method_name in self.method_cache:
return self.method_cache[method_name]
else:
def wrapper(*args, **kw):
wrapped = getattr(self.inner, method_name)
try:
return wrapped(*args, **kw)
except InnerDiedError:
self.inner = self.InnerFactory(innerType)
wrapped = getattr(self.inner, method_name)
return wrapped(*args, **kw)
self.method_cache[method_name] = wrapper
return wrapper
3
下面的代码大概能实现你想要的功能,但有几点需要注意:1)代码看起来不太好;2)它在多线程环境下不安全;3)它会陷入一个循环,直到Inner
中的某个方法抛出异常(这不是因为代码本身,而是因为最初的想法);4)还有其他一些原因不建议使用它 :)
class Inner:
def foo(self):
print "foo"
def bar(self):
print "bar"
class Outer:
def __init__(self):
self.inner = Inner()
def __getattr__(self, name):
ret = getattr(self.inner, name)
def wrapper(*args):
try:
ret(*args)
except:
del self.inner
self.inner = Inner()
updated = self.__getattr__(name)
updated(*args)
return wrapper
def blah(self):
print "Blah"
outer = Outer()
outer.foo()
outer.bar()
outer.blah()
outer.nosuchattr()