Ruby,Pythonで動的プロキシ
メタプログラミングRubyで動的プロキシというものが紹介されています
どのメソッドにも当てはまらないメッセージを他のオブジェクトに委譲する、というものです
下記はメタプログラミングRubyで紹介されているサンプルコードとほぼ同じものです
class MyDynamicProxy def initialize(target) @target = target end def method_missing(name, *args, &block) "result : #{@target.send(name, *args, &block)}" end end obj = MyDynamicProxy.new("a string") print obj.upcase # => result : A STRING
rubyではゴーストメソッド(method_missing)と動的ディスパッチ(sendによるメソッド呼び出し)を使って動的プロキシを実装しています
pythonで動的プロキシ
pythonではmethod_missingに近いものとして、__getattr__という特殊なメソッドがあります
メソッド呼び出しで該当するメソッドがオブジェクトツリーに見つからなかった場合に呼ばれます
class C: def __getattr__(self, attrname): return attrname.upper() obj = C() print obj.upper # => UPPER
動的ディスパッチについては、getattrを使って同等のことができます
method_to_call = 'upper' obj = "abc" getattr(obj, method_to_call)() # => "ABC"
参考)
Ruby、Pythonで動的ディスパッチ/動的メソッド定義
http://d.hatena.ne.jp/yuheiomori0718/20120116/1326715412
以上の__getattr__、getattrを使って、rubyのサンプルと同等のpythonコードは以下のように書けます
class MyDynamicProxy: def __init__(self, target): self.target = target def __getattr__(self, attrname): print("result : ") return getattr(self.target, attrname) obj = MyDynamicProxy("a string") print(obj.upper()) # => result: # => A STRING
ちょっとだけ異なる点として、rubyではmethod_missing内でtargetの処理まで呼び出しているのに対し、
pythonの__getattr__はtargetのメソッドオブジェクトを取得して返すだけで、処理自体は呼び出し元のスコープで行なっています。
__getattr__には引数は渡されませんので、引数の必要なメソッドの場合、内部で処理を行うことはできません
参考)
- 作者: Paolo Perrotta,角征典
- 出版社/メーカー: KADOKAWA/アスキー・メディアワークス
- 発売日: 2010/08/28
- メディア: 大型本
- 購入: 18人 クリック: 533回
- この商品を含むブログ (127件) を見る
- 作者: Mark Lutz,夏目大
- 出版社/メーカー: オライリージャパン
- 発売日: 2009/02/26
- メディア: 大型本
- 購入: 12人 クリック: 423回
- この商品を含むブログ (133件) を見る