PythonをRubyっぽく書くテスト

Dive Into Python

あたりを読んでいて思い付きました。何度目の車輪の再発明なのかは謎です。

まず、以下のようなクラスを定義します。

class Object:
	def __init__(self, instance):
		self.__dict__.update([(attr, getattr(instance, attr)) for attr in dir(instance)])
		self.instance = instance

	def __getattr__(self, attr):
		if hasattr(self.instance, attr):
			return getattr(self.instance, attr)
		else:
			return getattr(__builtins__, attr)(self.instance)

すると、

>>> i = Object(97)
>>> i.abs
97
>>> i = Object(97)
>>> i.chr
'a'
>>> i.complex
(97+0j)
>>> i.float
97.0
>>> l = Object([4, 2, 1, 3])
>>> l.sorted
[1, 2, 3, 4]
>>> l.min
1
>>> l.sum
10
>>> for i in l.reversed: print i,
... 
3 1 2 4
>>> s = Object('hoge')
>>> s.len
4
>>> s.index('o')
1
>>> s.type
<type 'str'>
>>> s.id
-1215441888

こんな感じに書けます。
要は、元のオブジェクトに該当するメソッドや属性がなかった場合、オブジェクトを第一引数にするような組み込み関数を、Rubyのメッセージのように呼び出せるわけです。

dirすると元のオブジェクト(intやlistやstring)と同じ属性を持っているのがわかると思います。

>>> l.dir
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', 
'__doc__', '__eq__', '__ge__', '__getattr__', '__getattribute__', '__getitem__', 
'__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__',
 '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__new__', '__reduce__', 
'__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', 
'__setslice__', '__str__', 'append', 'count', 'extend', 'index', 'insert', 'instance', 
'pop', 'remove', 'reverse', 'sort']

まあ、問題は、いちいち s = Object('hoge')みたいにするのがめんどくさいことなのですが。。(^^;
もしかしてこの辺の振る舞いもフック&自動化できたりするのかなぁ。