Rubyist のための他言語探訪 【第 1 回】 Python

著者:まつもとゆきひろ

編集:なかむら(う)

はじめに

「Rubyist のための他言語探訪」は、Ruby 作者まつもとゆきひろが、Ruby と関係があったりなかったりする他の言語を紹介していく連載です。 他の言語を知ることによって、視野が広がると同時に、逆に Ruby への理解も深まることでしょう。

第 1 回である今回は、オブジェクト指向、スクリプト言語、適用範囲、といった共通点から、多くの人から Ruby のライバルと目されている Python を紹介します。

歴史

Python は Guido van Rossum によって開発されました。 記録によると Python の開発は 1989 年のクリスマス休暇のプロジェクトとしてスタートしたのだそうです。 開発プラットフォームは Mac でした。 Python が UNIX くさくない理由はその辺にもあるのかもしれません。

Python の開発当初の目的は

  • 当時 Guido がかかわっていた分散 OS、Amoeba のスクリプト言語を作りたい。
  • 以前 Guido がかかわっていた教育用言語 ABC の影響を受けた言語を作りたい

というようなものでした。 開発段階のごく初期には Python はオブジェクト指向機能を備えていなかったようですが、Guido が DEC でインターンしていた時に使った経験のある Modula-3*1 からオブジェクト指向機能を取り込んで、最初にリリースされた時(1991 年 2 月)にはすでに「オブジェクト指向言語」であったと伝えられています。 第 1 引数が self となるスタイルなどが Modula-3 由来だということです。

こうしてみると Python の仕様には開発者である Guido の個人的な経験が大きく影響しているのを感じることができます。

1991 年の最初のリリースから 1995 年までは Python は Guido が所属していた CWI(Centrum voor Wiskunde en Informatica) の著作物として公開されていました。 1995 年に Guido はアメリカバージニア州レストンにある CNRI(Corporation for National Research Initiatives) に転職し、2000 年までは CNRI から Python がリリースされていました。 それからは BeOpen(2000 年 5 月から 10 月まで)、Digital Creation(現 Zope Corporation、2000 年 10 月から 2003 年 7 月まで)と移動しています。 現在は Guido は Elemental Security 社に所属し、セキュリティ関係の「表の仕事」と Python の開発を両立させているとのことです。

特徴

Python はわりと「普通」の言語です。 その中であえて普通でない特徴をあげてみます。

インデントベースのブロック構造

多くの言語では文の塊を表現するのにブレースや括弧でくくったり、「end」で終端を示したりするのですが、Python は「同じインデントレベルの文は同じ塊」というルールを採用しています。 これは見掛け上、Python のプログラムの最大の特徴となっています。

このインデントによるブロックは Python の専売特許ではありません。 たとえば、Occum や Haskell といった言語でも同じルールが採用されています。 Python 自身はこのルールを ABC から受け継いでいます。 ABC では文法に関してさまざまな研究が行われたようで、インデントを使うのが初心者にとってもっとも間違いにくいブロックの表現なのだそうです。

モジュール構造

Python は多くの機能がモジュールに分割され、使用する前に明示的に import する必要があります。 また、モジュール自身がひとつの名前空間となっています。 これは多くのスクリプト言語が持っていない機能です。 しかし、Java に親しんだ人ならむしろ普通に感じるかもしれません。

リスト閉包式/ジェネレータ閉包式

リスト(配列のようなデータ構造)やジェネレータ(C++ のイテレータのようなもの)を簡単に表現する記法です。 たとえば

[x**2 for x in range(10)]

は 0 から 9 までの数それぞれを自乗した値のリストになります。 このリスト閉包式の鈎括弧を丸括弧に置き換えるとジェネレータになります。

(x**2 for x in range(10))

は、for 文の繰り返し対象として与えると 0 から 9 までの数の自乗を順番に与えるジェネレータというオブジェクトを表現する記法です。 この記法は Haskell から受け継いだそうです。

Ruby との対比

Ruby ユーザの目から見ると Python の以下のような点が気になるかもしれません。

ブロック構造

インデントでブロック構造を表現すると Ruby に数多く登場する「end」が不要になります。 そのぶん、プログラムが縦方向に圧縮できるので望ましいような気がします。 スペースとタブが混在すると面倒なことになりますが、それはコーディングルールとして揃えれば良いことなので致命的な問題ではありません(デフォルトではタブはスペース 8 個とみなす)。

しかし、この文法では、ブロックを含む構文は値を持つ式として用いることができませんから、Rubyで頻繁に使われるブロック付きメソッド呼び出しのようなことはできません。 Python には名前のない関数を作る lambda という文法がありますが、関数本体部分には式ひとつしかかけないという大きな制限があるため、条件分岐ひとつ使うことができません。 そのような場合、Python では名前を付けた関数を定義し、その関数を引数として使うのが一般的のようです。 Ruby では

ary.map {|x| x**2}

となるものが、Python では

map(lambda x: x**2, ary)

となり、lambda の本体が1つの式では表現しきれなくなると

def mapper(x):
  .....

map(mapper, ary)

と書き換える必要があります。ブロックによるうれしさとのトレードオフの関係と言っても良いかもしれません。

もうひとつ、インデントによるブロック構造には、eRuby のような埋め込み型のテンプレートにおいてインデントレベルの維持が困難であるという欠点もあります。

self が多い

Python ではインスタンス変数のアクセスは「self.foo」のような形式で行います。 これは Ruby の「@foo」という形式に比べてタイプ量が多いので面倒と感じることがあります。 逆に Python ファンは「@」という記号を使うのが醜いと感じるようです。

イミュータブルな文字列

Python では文字列を書き換えることはできません。 効率を考えるとうれしくないのですが、オブジェクトの書き換えは面倒を引き起こすこともありますから、うれしくないことばかりでもありません。

タプルとリストの区別

Python には「配列」のようなデータ構造として、変更可能なリストと変更不可能なタプルのふたつをもっています。 このふたつの使い分けはときどき悩みのタネです。 慣れてしまうとどうということはないようですが。 リストは Ruby 同様、鈎括弧でくくります。 タプルは要素をカンマで区切って並べたものですが、普通は式の他の部分と区別するために丸括弧でくくります。要素がひとつしかない場合は、式のグループ化の括弧と区別が付きませんから、

(a,)   # (a)ではaと同じ

と書きます。

ドキュメントストリング

Python ではクラスやメソッドにドキュメントとなる文字列を付加することができます。 この文字列は実行中にプログラムから参照できます。 これは対話的環境で使っているときに特に便利です。

組み込みの対話処理系

Ruby における irb に相当するものが Python には最初から組み込まれています。 また、irb が eval を使って Ruby 自身で実装されたプログラムであるのに対して Python の対話処理系は Python インタプリタ自身が持つ機能ですから、動作の再現性に優れています。

一方、Ruby では irb は単なる Ruby プログラムですから、Ruby を使って簡単に機能を拡張できます。 メソッド名などを補完する機能、ヒストリ機能、またドキュメント参照機能などを追加するプログラムが公開されています。

まとめ

今回は、機能やポジション的にかなりオーバーラップすると考えられる Python を Ruby との対比という視点から見てみました。

まとめると Python は良い言語です。 海外で人気なのも分かる気がします。 記号含有率が低いし、プログラムがより「普通」に見えるのも利点だと思います(インデントによるブロック構造を除く)。 しかし、Ruby よりちょっと回りくどいところもあり、そこが気に入らない人もいるでしょう。 純粋にスクリプト言語として小規模なプログラムの開発に使うのであれば Ruby の方が使い易いことが多いように思います。 また、ある程度以上のプログラムの開発の場合、Python を好む人も多いでしょう。 オブジェクト指向機能に限定すれば Ruby の方がより「純粋」ですが、Python の方が「劣っている」ということはありません。

しかし、言語の「勝敗」を決めるのに技術的要因はわずかです。最終的に重要なのは、

  • 得られる情報の量と質
  • 利用できるライブラリの量と質
  • 自分の好みに合うか

などです。 結局は好みによって決まるのかもしれません。 英語圏のことまで考えると、情報やライブラリの量や質でまだまだ Ruby は Python に負けているので、胸を借りるつもりで切磋琢磨できればと考えています。

次回の言語

次回は、Ruby に影響を与えた言語の一つ、CLU を紹介する予定です。 お楽しみに!

参考文献

Python Programming Language
Python の公式サイト(英語)。Python に関する一次情報はこちらへ。
日本 Python ユーザ会
Python に関するニュースや豊富な日本語ドキュメントなどが得られます。実際に Python を使ってみたい人にはチュートリアルが、より深く Python を知りたい人にはリファレンスマニュアルなどが役に立つでしょう。

著者について

elephant_at_hokudai.jpgまつもとゆきひろは自他ともに認める日本を代表する言語オタクです。 言語好きが昂じて自分の言語を設計してしまった大馬鹿者です。 が、オタクとかハッカーとか呼ばれる人種はみんな多かれ少なかれそんなものじゃないでしょうか。

*1 DEC リサーチセンターで Trellis/Owl という言語の後継として開発された言語。名前が示す通り、Pascal の開発者 Niklaus Wirth の Modula-2 から影響を受けているが、Modula-3 の開発には Wirth は関係してないらしい。