Pythonでmixin
昨日のまとめ。
まずモジュールを利用する場合はモジュールに関して以下を知っておく必要がある。
sys.modules[module_name] = module_objで、モジュールを追加することができる。ここで、module_objには「属性を持ったオブジェクト」なら何でもOK。つまり、以下の3通りのどれでもモジュールとして認識できる。int値など全てのオブジェクトもモジュールになり得るが、Noneはimportした際にエラーがでる。また、reload()の引数はモジュールオブジェクト以外だとエラーになる。ここでは属性を持てるもののみ考える。
- 関数
- クラス
- モジュール
ここで、属性が関数である場合にクラスだけ特殊な意味を持つ。以下を考えてみる。
>>> class Foo: ... def foo(self):pass ... >>> class Bar: ... def foo(self):pass ... >>> Bar.foo = Foo.foo >>> Bar.foo <unbound method Foo.foo> >>> Bar.foo(Foo()) >>> Bar.foo(Bar()) Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: unbound method foo() must be called with Foo instance as first argument (got Bar instance instead)
つまり、属性が関数の場合、(恐らく参照時に)関数が所属するクラスの情報を持ったメソッドに自動的に昇格する。
ここでさらに、Pythonで何らかの機能を追加する方法は以下の通り。
- 継承
- 委譲
- デコレータ
- import
- 属性をコピー
ここで、mixinとは何かについて考える。私の考えでは、以下の2つで表現できるのではと考える。実はmixinとして成立する条件は私自身理解していない。wikipediaでmixin調べたけどよく分からなかった。
- 属性をコピーする
- コピーされた属性がコピー元の情報を持たない
すると、継承、委譲は使えない。デコレータももちろん使えない。結局、setattr()やa=bやFoo.__dict__(新スタイルクラスの場合はdictproxyでread-only)もしくは、importのどれかしかないのかなと思う。『Pythonクックブック 第2版』とかで__getattr__などを利用しDelegateする方法が載っているが、それだとmixinではないのかなと思っている。
結局、クラスの定義部分で一気にmixinするにはimportする方法が1つ。後は、inspectを利用して何かできないだろうか?あと、メタクラスを利用したら継承になるのでダメなのだろうか?やはりまずmixinの本質を理解しないとダメかも。
次世代言語Scala
今まではC言語から新しい言語を作るのが主流だったが、今の時代VM上で動く言語から新しい言語を作るのが主流になりつつある。その中でもScalaは抜きん出ていると思う。yieldを使うと外部イテレータでなく内部イテレータになることや"1 + 2"が"1.+(2)"の意味などRubyismが入っているのはPythonistaとしては気になったが、Rubyと違って関数がファーストクラスオブジェクトであることや、構文がシンプルなのは良い。
今の時代、C言語ができますというのはプログラミングできませんと言っているのと同じで、これからはJavaができますというのは通用しなくなってくると思う。
追記(2008/2/27):
誤解されそうなので追記。一部の分野ではC、Fortran、COBOLなどのエキスパートを必要とする仕事があるので、もちろんそれだけしかできなくてもプログラミングができない訳ではない。エキスパートなら他の人が知らないことまで知っている。
但し私の考えではそういう分野の人はプログラミングの全てを理解していると思っている傾向がある気がするが、狭い分野の知識だけでは新しい分野の知識に関しては無知と言えると思う。例えばCしか知らない人がstaticとは何かについて一般的な説明をできないと思う。また別の例ではC++しかしらない人は100個のデータ型があったら100個をベタ書きする。ここではvirtualかどうかは重要ではない。まさかTemplateを駆使してメタプログラミングはしないだろうと思う。
自分のいる分野では新しい技術が使えないと思っている人が多すぎる。Scalaどころか、実績が多数あるのにJavaすら使えない、あるいは勉強する気がないという人が多すぎる。