如果只是一种方法,那么你得到的东西并不是那么糟糕。它很直截了当地说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
是唯一需要委托给包含的实例的方法。如果你想委托方法很多,那么有一些选项:
如果你想的Foo
所有方法是从含有Foo
的Bar
情况下可调用的,那么你可以尝试使用__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
是一个Foo
围绕一个简单的包装,因为那时“一Bar
行为大多喜欢一个Foo
”是概念上的接口(而不是Foo
是内部的一部分实现细节),并且它减少了Bar
的定义,以描述它的方式为而不是,如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
)。但是隐藏在类装饰器中隐藏这样做的逻辑是相对容易的,这会让你能够创建更多的类,将其某些方法的实现委派给它们的一个属性。
在这些你可以想到的事情上有许多变化。
来源
2012-08-10 06:47:07
Ben
但是,如果'baz'只是一种实用方法,并且没有与Bar有关的状态,那么你就不需要一个类。你只需要功能 – jdi 2012-08-10 05:38:05