如果只是一種方法,那麼你得到的東西並不是那麼糟糕。它很直截了當地說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