2014年9月25日木曜日

Rubyistが歩んでみる蛇の道はPython その6

Dive into Python 3のchapter 7を読んでみたのだが、Classes & Iteratorsなんて章の名前を付けている割に、そんなにクラスについて詳しく書いていない。具体的な継承の話なんか、まるで無いし。そこでググってみたところ、こちらの公式チュートリアルが良さそうなので、ざっと読んでみた。

多くの人が真っ先に面食らうのは、Rubyを含む多くのオブジェクト指向な言語ではimplicitに渡されるのが当たり前のselfやらthisやらが、Pythonのメソッド定義ではexplicitに第1引数として、インスタンス自身が渡される点だろう。この第1引数はselfという名前を使うことを推奨されているようだけれど、selfは単なる仮引数の名前であって予約語でも何でも無い。

そしてメソッド定義の中でさえ、インスタンス変数にはselfを介さないとアクセスできない。言い換えると、インスタンス変数はスコープに入らないのだ。Rubyだと

def method
  @member1 = 100
  print(@member2)
end
のようにアクセスできるところが、Pythonだと
def method(self):
  self.member1 = 100
  print(self.member2)
のようにせねばならない。

地味に嫌らしいと思うのが、Pythonではクラスのインスタンスを介してクラス変数にアクセスできる点。Pythonだと

class Foo:
  x = 100

foo = Foo()
print(foo.x)
こんなことが出来てしまう。Rubyでクラス定数を参照しようと思ったら
class Foo
  X = 100
end
print(Foo::X)
print(Foo.new.X) # error
のように、インスタンスではなくクラス名の修飾が必要。

他にも、public, protected, privateと言ったアクセス制限の機能がPythonにはない。_memberみたいに'_'を付けたメンバはprivate扱いしてね、みたいなコーディングルールで凌いでいるようだ。まあLLならそれくらいの緩さでも許されるだろう。

問題は継承。ずばり、Pythonは多重継承が出来る。これだけでもう、Rubyで言うところのmix-inだの、Javaで言うところのinterfaceだの、そんな細かい話は吹っ飛んでしまう。属性の検索が基本的に深さ優先探索で行われるというのも要注意だろう。A, Bの順に多重継承した場合、BよりAの曾祖父の方が先に探索されるのだ。実装を考えればそりゃそうなんだろうけど、普段から多重継承が制限された世界で過ごしていると違和感を禁じ得ない。

0 件のコメント:

コメントを投稿