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