Ruby、Pythonで動的ディスパッチ/動的メソッド定義
動的ディスパッチ
動的ディスパッチは、「実行時に呼び出すメソッドを決める」ことを指します。
rubyではsendによって動的ディスパッチができます
method_to_call = :upcase obj = "abc" obj.send(method_to_call) # => "ABC"
pythonではメソッドがオブジェクトなので、getattrを使って、メソッドオブジェクトを取得して、実行することができます
method_to_call = 'upper' obj = "abc" getattr(obj, method_to_call)() # => "ABC"
動的メソッド定義
動的メソッド定義は「実行時にメソッドを定義する」ことを指します。
rubyではdefine_methodを使用して動的にメソッドを定義することができます
以下は英語版wikipediaのrubyのページに記載されている例です
COLORS = { :black => "000", :red => "f00", :green => "0f0", :yellow => "ff0", :blue => "00f", :magenta => "f0f", :cyan => "0ff", :white => "fff" } class String COLORS.each do |color,code| define_method "in_#{color}" do "<span style=\"color: ##{code}\">#{self}</span>" end end end "Hello, World!".in_blue => "<span style=\"color: #00f\">Hello, World!</span>"
Stringにメソッドを動的に追加しています。define_methodを使うことによって、記述量を減らしています
pythonではメソッドがオブジェクトなので、setattrを使って、メソッドオブジェクトをクラスにセットすることができます
ただ、ビルトインクラスであるstrにメソッドを追加することはできませんので、strを継承したクラスを作成する必要があります
colours = {"black": "000", "red": "f00", "green": "0f0", "yellow": "ff0", "blue": "00f", "magenta": "f0f", "cyan": "0ff", "white": "fff"} class MyString(str): pass for name, code in colours.iteritems(): def _in_colour(self, code=code): return '<span style="color: #%s">%s</span>' % (code, self) setattr(MyString, "in_" + name, _in_colour) print MyString("Hello, world!").in_blue() # => <span style="color: #00f">Hello, world!</span>
参考)
Wikipedia(Ruby (programming language))
http://en.wikipedia.org/wiki/Ruby_%28programming_language%29
Python's equivalent for Ruby's define_method?
http://stackoverflow.com/questions/5449244/pythons-equivalent-for-rubys-define-method
Ruby、Pythonでクラスのインスタンスメソッドを追加する
http://d.hatena.ne.jp/yuheiomori0718/20120114/1326545228