如果这只是一种方法,那么您所拥有的确实还不错。它直截了当地说这baz
是 的接口的一部分Boo
,它通过委托给包含的Foo
实例来实现这一点。
稍微短一点的版本是使用属性:
class Foo (object) :
def baz (self) :
return 324
class Bar (object) :
def __init__ (self) :
self.foo = Foo()
@property
def baz(self):
return self.foo.baz
def __getattr__(self, attr):
return getattr(self.foo, attr)
bar = Bar()
print bar.foo.baz()
print bar.baz()
baz
尽管如此,仍然有一个额外的函数调用,而且它可能是一个方法不太明显。
如果不求助于重写您的继承树,我只会使用您所拥有的,如果baz
是唯一需要委托给包含的实例的方法。如果你想委托许多方法,那么有一些选项:
如果您希望所有方法都可以从包含 aFoo
的实例调用,那么您可以尝试使用:Bar
Foo
__getattr__
class Foo (object) :
def baz (self) :
return 324
class Bar (object) :
def __init__ (self) :
self.foo = Foo()
def __getattr__(self, attr):
return getattr(self.foo, attr)
bar = Bar()
print bar.foo.baz()
print bar.baz()
但这有一些明显的缺点。
Bar
通过阅读源代码或通过自省,目前尚不清楚实际提供了什么方法。
- 的所有
Foo
方法和属性(不是由 直接提供的Bar
)都将通过Bar
的接口公开,这可能是不可取的。
当然,您可以在__getattr__
方法中加入更多逻辑,只委托某些事情,而不是所有事情。
Bar
当所有 a都是 a 的简单包装器时,我倾向于采用这种方法Foo
,因为“a 的Bar
行为主要像 a Foo
”是概念接口的一部分(而不是Foo
内部实现细节),并且它减少了Bar
's定义来描述它不像Foo
.
另一种方法是使用 Python 的动态特性来定义Bar
该委托的属性,Foo
而无需全部手写。像这样的东西可以解决问题:
class Foo (object) :
def baz (self) :
return 324
class Bar (object) :
def __init__ (self) :
self.foo = Foo()
for _method in ['baz', 'blob']:
@property
def _tmp_func(self, _name=_method):
return getattr(self.foo, _name)
locals()[_method] = _tmp_func
# del to avoid name pollution
del _method, _tmp_func
bar = Bar()
print bar.foo.baz()
print bar.baz()
这种方法相对于__getattr__
一种方法的优点是,您有一个明确的方法列表,当您阅读代码时这些方法被重定向,并且它们Bar
在运行时都“看起来像”正常属性,因为它们是正常属性。如果您只需要一两个方法,那么它显然比您的原始代码要多得多!而且它有点微妙(由于 Python 闭包的工作方式,需要通过默认参数_method
传入_tmp_func
并不一定很明显)。但是在类装饰器中隐藏执行此操作的逻辑相对容易,这将使您能够创建更多类,将它们的某些方法的实现委托给它们的属性之一。
你可以想出很多关于这些事情的变体。