メソッドのself (4)

メソッドの第一引数にselfを指定する1つのメリットを見つけた。Guidoさんも言及していたかもしれないがメリットは、foo.meth(arg)を、Foo.meth(foo, arg)と書けることである。これは、高階関数として使う場合にメリットがある。


例えば、複数のsetのオブジェクト全てにintersectionをしたい場合、以下のようにできる。

>>> s1 = set([1,2,3])
>>> s2 = set([2,3,4])
>>> s3 = set([3,4,5])
>>> L = [s1, s2, s3]
>>>
>>> s1.intersection(s2)
set([2, 3])
>>> set.intersection(s1, s2)
set([2, 3])
>>>
>>> reduce(set.intersection, L)
set([3])

これとは違うが、3.0に面白いメソッドが追加されていて、以下のようなことができる。

>>> import operator
>>> s1 = {1,2,3}
>>> s2 = {2,3,4}
>>> operator.methodcaller('intersection', s2)
<operator.methodcaller object at 0x00CBF1E8>
>>> _(s1)
{2, 3}

結局、メソッドのレシーバや引数を自由に入れ替えできるような機能があれば、OKかもしれない。


追記(2008/12/10):

operator.methodcallerは残念ながら引数としてレシーバのみを取る関数しか戻してくれない。以下のようにできない。

>>> import operator
>>> operator.methodcaller('intersection')
<operator.methodcaller object at 0x00CBF1E8>
>>> _(s1, s2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: methodcaller expected 1 arguments, got 2

Haskellのように自動的にカリー化される機構があれば以下のようにできる。

>>> operator.methodcaller s2 s1  # この場合s1とs2は対称で交換可能なので methodcaller s1 s2でも良い

Haskellのような1引数しか取れないという仕組みはどうなのだろう?関数のカッコは面倒だが、カッコを省略できるということに関してあまり良いイメージがない。