火曜日はメソッドを動的に定義する。Pythonだと__setattr__と__getattribute__を使えばいいが、魔術っぽさを感じる。Rubyは見た目自然じゃないか。
import re
class Ds(object):
def get_cpu_info(self,i):
return 2.16
def get_cpu_price(self,i):
return 150
def get_mouse_info(self,i):
return "dual optical"
def get_mouse_price(self,i):
return 40
# METAPROGRAMMING RUBY
# class computer
# def initialize(computer_id, data_source)
# @id = computer_id
# @data_source = data_source
# data_source.methods.grep(/^get_(.*)_info$/) { Computer.define_compornent $1}
# end
#
# def self.define_component(name)
# define_method(name){
# info = data_source.send "get_#{name}_info", @id
# price = data_source.send "get_#{name}_price", @id
# result = "#{name.capitalize}: #{info} ($#{price})"
# return "* #{result}" if price >= 100
# result
# }
# end
# end
class Computer(object):
def __init__(self,computer_id, data_source):
self.data_source = data_source
self.id = id
for name in [re.search("^get_(.*)_info$",m).group(1) for m in
dir(data_source) if re.search("^get_(.*)_info$",m)]:
self.define_compornent(name)
def define_compornent(self, name):
def define_method():
info = self.data_source.__getattribute__("get_%s_info"%name)(self.id)
price = self.data_source.__getattribute__("get_%s_price"%name)(self.id)
result = "%s: %s ($%s)" % (name.capitalize(), info, price)
if price >= 100:
return "* %s" % result
self.__setattr__(name,define_method)
if __name__ == '__main__':
ds = Ds()
com = Computer(12,ds)
print com.mouse()
print com.cpu()
後半はmethod_missingを使う例だった。perlだとAUTOLOADかとおもってググッてみたら。一覧になってた。
ところで、__getattribute__と__getattr__の違いがわからんという新たな発見をした。