自動委譲と__getattr__
Decoratorパターンの項でも書きましたが、「メンバのメソッドに丸投げするメソッド」をしばしば書く必要が出てきます。
class WriterDecorator(object): #以下のメソッドは単にwriterに丸投げ def writeline(self, line): return self.writer.writeline(line)
の様に。そこで、こういうのを自動的に行うようにします。
やり方は数種類あるようです。
方法1:__init__で属性をセット
一番分かりやすい方法です。getattr(self.writer, name)で、self.writerのbound methodを取れるのを利用します。
class SimpleWriter(object): def __init__(self, path): self.file = open(path, "w") def writeline(self, line): print >> self.file, line def pos(self): return self.file.tell() def rewind(self): self.file.seek(0) def close(self): self.file.close() class WriterDecorator1(object): deligates = "writeline pos rewind close".split() def __init__(self, writer): self.writer = writer for method_name in self.deligates: method = getattr(self.writer, name) setattr(self, name, method)
方法2:__getattr__
w.spam のように、属性を取り出そうとしたが、
wがspamという属性を持っていなかったとき、__getattr__が呼ばれるので、
__getattr__の中で、委譲相手のメソッドを取って来ます。
委譲したいメソッドの数が多く、書き並べるのが面倒な場合に便利な方法です。
もちろん、指定したメソッドだけ委譲することも出来ます。
class WriterDecorator2(object): def __init__(self, writer): self.writer = writer def __getattr__(self, name): #自分に無い属性はてself.writerからとって来る return getattr(self.writer, name) ##def __getattr__(self, name): ## #指定した属性だけself.writerからとって来る ## deligates = "writeline pos rewind close".split() ## if name in deligates: ## return getattr(self.writer, name) ## else: ## return object.__getattr__(self, name)
ちょっと黒い自動委譲
に続きます。