それがただ1つの方法であるなら、あなたが持っているものは正直言ってそれほど悪くはありません。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
呼び出し可能にする場合は、次を使用してみてください。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
、「aBar
はほとんどのように動作する」が(内部実装の詳細Foo
ではなく)概念インターフェイスの一部であり、それがのようではない方法を説明するための定義。Foo
Bar
Foo
もう1つのアプローチは、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
ため、実行時にの通常のプロパティのように見えることです。ただし、これが1つまたは2つのメソッドにのみ必要な場合は、明らかに元のコードよりもはるかに多くのコードになります。そしてそれは少し微妙です( Pythonのクロージャが機能する方法のためにデフォルトの引数_method
を_tmp_func
介して渡す必要があることは必ずしも明白ではありません)。ただし、クラスデコレータでこれを行うためのロジックをパッケージ化するのは比較的簡単です。これにより、メソッドの一部の実装を属性の1つに委任するクラスをさらに作成できるようになります。
あなたが思いつくことができるこれらの種類のものには多くのバリエーションがあります。