2010年7月13日火曜日

import thisとThe Zen of Python

原文:http://python-history.blogspot.com/2010/06/import-this-and-zen-of-python.html
原文投稿者:Guido van Rossum

Barry Warsaw氏が、Pythonの歴史の中で、今まで明らかにされていなかった(記録に残したい)事実を紹介する面白いエントリーをブログに投稿している。

http://www.wefearchange.org/2010/06/import-this-and-zen-of-python.html

2010年7月8日木曜日

新スタイルクラスの内部の話

原文:http://python-history.blogspot.com/2010/06/inside-story-on-new-style-classes.html
原文投稿者:Guido van Rossum

[注意:この投稿はとても長くて技術的です]

表面上は、新スタイルクラスは、元々のクラスの実装と非常に似通って見えるが、新スタイルクラスでは次のような数々の新しいコンセプトが導入されている。

  • __new__()という名前の低レベルのコンストラクタ
  • 属性アクセスのカスタマイズを一般的にできるようにするデスクリプタ
  • 静的メソッドとクラスメソッド
  • プロパティ(演算してから結果を返す属性)
  • デコレータ(Python 2.4から導入)
  • スロット
  • 新しいメソッド解決順序(Method Resolution Order, MRO)

このエントリーでは、これらのコンセプトについて光を当てていこうと思う。

__new__()という名前の低レベルのコンストラクタ

クラスを定義するときには通常の場合には、インスタンスの生成後にどのように新しいインスタンスを初期化するのかを定義する、__init__()メソッドを実装していた。しかし、クラスの作者が、インスタンスの生成方法そのものもカスタマイズしたいというケースがいくつかある。例えば、オブジェクトを永続化されたデータベースから復元する場合などである。"new"モジュールなど、普通ではない方法で特定の種類のオブジェクトを作成するためのライブラリはいくつかあったが、旧スタイルクラスではオブジェクトの生成をフックしてカスタマイズする方法が提供されていなかった。

新スタイルクラスでは、__new__()という新しいクラスメソッドが提供されたことで、クラスの作者が新しいクラスのインスタンスを生成する方法もカスタマイズできるようになった。__new__()メソッドをオーバーライドして、以前作成したインスタンスを返すことで、クラス作者はシングルトンパターンのようなパターンも実装することが可能である。また、他のクラスのインスタンスも返すことができる。しかし、__new__()の活用法には、これ以外にももっと重要なものがある。例えば、pickleモジュールでは、__new__はシリアライズされたオブジェクトを復元してインスタンスを作成するのに使用されている。このケースでは、インスタンスは生成されるが、__init__()メソッドは呼び出されないという実装になっている。

他にも、変更不可(immutable)型のサブクラス化を行う際にも、__new__が役に立つ。変更不可能という特性上、標準的な__init__()メソッドでは、このようなオブジェクトを初期化することはできない。そのため、オブジェクトの作成時に何か特別な初期化処理を行う必要がある。もし、変更不可能なオブジェクトの中に格納される値を変更したい場合には、ベースクラスの__new__メソッドに変更後の値を渡すことによって、このような処理を行うのに利用できる。

デスクリプタ

デスクリプタは、旧スタイルクラスの実装の中心となっている、束縛メソッドの概念を一般化したものである。旧式のクラスでは、インスタンス属性がインスタンス辞書の中から見つけられない場合には、クラス辞書を引き続き探索し、その後はベースクラスのクラス辞書を再帰的にたどっていくという振る舞いをする。もし属性がクラス辞書の中で見つかると、インスタンス辞書とは異なり、インタプリタが見つかったオブジェクトがPythonの関数オブジェクトであるかどうかがチェックされる。もし、そのオブジェクトが関数オブジェクトだった場合には、見つけたオブジェクトを返値にするのではなく、カリー化関数のように振る舞うラッパーオブジェクトを返す。ラッパーが呼ばれると、インスタンスを引数リストの先頭に挿入してから、オリジナルの関数が呼び出される。

例えば、クラスCのインスタンスxがあると想定しよう。今、このインスタンスに対して、x.f(0)という呼び出しが行われたとする。この操作を分解すると、まず、"f"という名前の属性をインスタンスxから探しだし、引数として0を渡して呼び出される。もし、"f"がクラスの中で定義されたメソッドと一致するのであれば、次の擬似コードの関数のような振る舞いをするラッパー関数を属性として返す:

def bound_f(arg):
    return f(x, arg)

もしも引数の0とともにこのラッパーが呼ばれると、このラッパー関数はx0という二つの引数をともなって"f"を呼び出す。これが、クラスのメソッドが"self"引数を取得する基本的なメカニズムである。

(ラップされていない)関数オブジェクトfにアクセスする別の方法としては、クラスCの属性として"f"という名前の属性の問い合わせをするというものがある。このような検索を行うと、ラッパーのつかない、関数fを単純に返す。言い換えると、x.f(0)は、C.f(x, 0)と同じということである。Pythonの中では、これらの呼び出しは基本的に等価である。

旧式のクラスでは、属性を調べて、他の種類のオブジェクトが見つかった場合には、ラッパーは生成されずに、クラス辞書の中から見つかったオブジェクトがそのまま返される。これにより、クラス属性をインスタンス変数の"デフォルト"値として利用することもできる。例えば、上記の例であれば、もしクラスCが"a"という属性名で数値の1を持っていて、xのインスタンス辞書に"a"というキーがなければ、x.a1となる。x.aに割り当てると、xのインスタンス辞書に"a"というキーができ、属性辞書の探索順序の影響でクラス属性の値が隠蔽される。x.aを削除すると、隠されていた値(1)に再びアクセスできるようになる。

残念ながら、何人かのPython開発者により、この実装の限界が発見されてしまった。限界の一つ目が、いくつかのメソッドPythonで実装し、他のメソッドをCで実装するという"ハイブリッド"クラスを実装することができないというものである。これはPythonの関数だけが上記のような方法でインスタンスにアクセスするためのメソッドを提供していたのと、この振る舞いが言語にハードコードされていたのが原因である。また、C++やJavaプログラマーが親しんでいる、静的メンバー関数のような異なる種類のメソッドを定義する方法もなかった。

この問題に対処するために、Python 2.2からは、上記のラッピングの振る舞いを素直に一般化した仕組みが導入された。Pythonの関数オブジェクトのみをラップするというハードコーディングされた振る舞いの代わりに、属性検索で見つかったオブジェクト(上記の例だと関数f)ごとにラッピングするようになった。もしオブジェクトが見つかると、__get__と呼ばれる特殊なメソッド名を持つ、「デスクリプタ」と呼ばれるオブジェクトが返される。次に__get__メソッドが呼ばれ、属性検索の結果として、このメソッドの返値が使用される。もしオブジェクトが__get__メソッドを持っていない場合には、それがそのまま返される。インスタンス属性検索コード内に特別な処理を行う関数オブジェクトを作らずに、関数オブジェクトをラッピングして返すという今まで通りの振る舞いにするために、関数オブジェクトには、以前のコードと同じようなラッパーを返す、__get__メソッドが追加された。このデフォルトのラッパー以外にも、ユーザが自由に__get__というメソッドを持つ他のクラスを定義し、インスタンス属性検索中でクラス辞書の中から発見された場合に、好きなようにラッピングすることもできるようになった。

属性検索コンセプトを一般化するのに加え、属性の設定と削除の操作にも、このアイディアを拡大して適用した。x.a = 1del x.aなど、今までと同じような割り当て操作を使用することができる。このような操作が行われた時に、"a"という属性がインスタンス辞書ではなく、インスタンスのクラス辞書の中で発見された時に、クラス辞書に保持されたオブジェクトに__set____delete__という特別メソッドがないかどうかチェックされる。(__del__というメソッドはまったく別の意味で既に使用されている。そのため、これらのメソッドを再定義することによって、デスクリプタオブジェクト属性の取得、設定、削除の操作の時にどのような処理が行われるかを、完全に制御することができる。しかし、デスクリプタインスタンスが、インスタンス辞書ではなく、クラス辞書内に設定された時にだけ適用されるという点は、重要なので最後にもう一度強調しておきたい。

staticmethod, classmethod, property

Python 2.2からは、classmethod, staticmethod, propertyという、新しいデスクリプタのメカニズムに関連する、3つのクラスが追加された。classmethodstaticmethodは、関数オブジェクトに関するシンプルなラッパで、保持している関数オブジェクトの呼び出し方が通常とは異なるラッパーを返す、__get__メソッドが実装されている。例えば、staticmethodのラッパーは、引数リストに変更をいっさい加えずに関数を呼び出す。classmethodのラッパーは、インスタンスそのものではなく、インスタンスのクラスを引数の先頭に追加してから関数を呼び出す。呼び出されるのがインスタンス経由であっても、クラス経由であっても、それぞれの引数は一緒となる。

propertyクラスは、"属性"に対する値の設定と、"属性"からの読み込みに関する対となる2つのメソッドを持つようなラッパーを生成する。例えば次のようなクラスがあったとする。

class C(object):
   def set_x(self, value):
       self.__x = value
   def get_x(self):
       return self.__x

propertyラッパーを使うと、属性"x"にアクセスされたときに、値の読み込みと設定に、ここで定義されたget_x, set_xメソッドが暗黙的に呼び出されるようにすることができる。

最初にclassmethod, staticmethod, propertyが導入されたときには、これらを簡単に扱える、特別な文法がなかった。そのときは、新しい文法(常に激しい議論が巻き起こる)と一緒に新しい機能を導入しようとすると、議論が収束しなくなって、導入できなくなると考えられたので、機能の追加だけが行われた。そのため、この機能を使用する場合には、通常通りクラスとメソッドを定義したあとに、メソッドをラップするための追加の文を追加する必要があった。

class C:
   def foo(cls, arg):
       ...
   foo = classmethod(foo)
   def bar(arg):
       ...
   bar = staticmethod(bar)

プロパティについても、同様の作法に従っていた。

class C:
 def set_x(self, value):
    self.__x = value
 def get_x(self):
    return self.__x
 x = property(get_x, set_x)
デコレータ

デスクリプタのやり方の不都合な点は、メソッド定義の最後まで読まないと、そのメソッドが静的メソッドが、クラスメソッドか、あるいはその他のユーザ定義の属性を持つメソッドか特定できないという点である。Python 2.4からは、最後に新しい文法が導入され、次のように書くことができるようになった。

class C:
 @classmethod
 def foo(cls, arg):
    ...
 @staticmethod
 def bar(arg):
    ...

@式 というのを、関数定義の前の行に書くことができるようになった。この構文を、デコレータと呼ぶ。__get__を実装したラッパーを作成するデスクリプタと混同しないようにして欲しい。デコレータ構文の文法(Javaのアノテーションから派生)に関しての議論は、「BDFL宣告」によって文法が決定されるまで、延々と続いた。(David BeazleyはBDFLと言う用語の歴史に関しては、私が書いたものとは別々に書いている)。

デコレータ機能は、言語の機能の中で、もっとも成功したものとなった。「うまくいけばここまで広がるだろう」と予想していた範囲いっぱいまで、幅広くカスタムデコレータが使用された。特にウェブフレームワークはこの文法の使用方法について、さまざまな発見をして応用された。この成功を受けて、Python 2.6からは、この文法は関数定義だけではなく、クラス定義でも使用できるように拡張された。

スロット

デスクリプタの導入によって可能になった別の拡張機能としては、クラスの__slots__属性がある。例えば、次のようにクラス宣言が行える

class C:
 __slots__ = ['x','y']
 ...

スロットが定義されると、いくつかのことが行われる。まず最初に、リストに定義されたのと同じ名前の属性しか、オブジェクトに定義できないように制限される。次に、属性が固定されると、それ以上はインスタンス辞書に属性を保持する必要がなくなるため、__dict__属性が削除される。ただし、ベースクラスにはそれがあり、__slots__を利用しないサブクラスで利用される。__dict__の代わりに、配列を使用して、予約された場所に属性が保存される。そのため、すべてのスロットの属性は、それぞれの属性が格納される配列のインデックスを知っている、デスクリプタのオブジェクトが割り当てられる。この機能の実装は、完全にC言語で構築されているため、とても効率が良い。

中には、__slots__を導入した目的が、属性名を制限することによるコードの安全性の向上であると誤解している人もいる。実際には、私の究極の目標はパフォーマンスであった。導入の動機としては、__slots__はデスクリプタの面白い応用例であったから、というのもあったが、これらの新スタイルクラスに導入された変更は、パフォーマンスに対して深刻な影響を与えるのを恐れていたからである。特に、データデスクリプタを適切に動作させるには、オブジェクトの属性に対するあらゆる操作をする前に、データデスクリプタの場合には、まずその属性があるかどうか、クラス辞書を先に見に行く必要がある。その場合には、手動でインスタンス辞書を操作する代わりに、デスクリプタが使用されて属性アクセスが行われる。しかし、このようなチェックを追加する場合には、インスタンス辞書にアクセスする前に、追加の検索が実行されるということを意味している。スロットを利用することでパフォーマンスを向上させることができるため、万が一、新スタイルクラスを導入して、そのようにパフォーマンスの劣化で失望した場合に利用することができる。後になって(パフォーマンスの劣化が思ったよりも少なくて)、不必要であることが分かったが、その時にはもう削除するには遅かった。もちろん、適切に使用すれば、スロットはパフォーマンスを実際に増加させられる。特に、小さいにオブジェクトが大量に作成される場面では、メモリの使用量の削減によって、大きくパフォーマンスは向上する。

次の投稿では、Pythonのメソッド解決順序(MRO)の歴史に触れてみたいと思う。

2010年6月26日土曜日

新スタイルクラス

原文:http://python-history.blogspot.com/2010/06/new-style-classes.html
原文投稿者:Guido van Rossum

以前、Pythonへのクラスの追加は、本質的には後付であったという説明を行った。実装の選択は、Pythonの「手抜きをする」という哲学に従って行われた。しかし、Pythonが進歩するに従い、エキスパートのPythonユーザは、クラスの実装の問題について頻繁に不満を述べるようになってきた。

クラスの実装の1つの問題は、組み込み型のサブクラス化を行う方法がなかったということである。例えば、リスト、辞書、文字列やその他のオブジェクトは何か「特別」なもので、サブクラス化して、一部を特殊化することができなかった。この制限は、「オブジェクト指向である」と主張していた言語にしては、奇妙に見えてしまっていた。

他の問題は、型システムが全般的に、ユーザ定義クラスに関しては「間違っている」ようにしか見えなかったことである。例えば、まったく別の関係ないクラスのユーザ定義の2つのオブジェクトのabがあったとすると、type(a) == type(b)を評価すると、真になってしまうのである。言うまでもなく、C++やJavaなどの、クラスが言語の型システムと密接に結びついているような他の言語に明るい開発者から見ると、かなりおかしく見えた。

Python2.2では、しっかりと時間をとって「正しく動作する」ようにクラスの再実装を行った。この変更は、Pythonのサブシステムをもっとも大々的に書き直したものとなったため、人々からは、この努力に対して「セカンドシステム症候群である」という非難を受ける可能性もあった。この変更では、組み込み型の継承ができないという問題を手っ取り早く修正するだけではなく、真のメタクラスのサポートの追加、多重継承時のメソッド解決順序という難しい問題の修正、その他の多くの機能の追加を行った。この仕事においては、"Putting Metaclasses to Work"という、Ira FormanとScott Danforthが書いた本の影響を強く受けている。この本は、Smalltalkとも違う、メタクラスが何かという示唆を私に提供してくれた。

クラスの書き直しに関しての面白い点は、旧スタイルクラスと置き換えて導入したのではなく、新しい言語機能として新スタイルクラスを導入したということである。後方互換性のために、Python 2のクラス作成プロトコルのデフォルトとして、旧スタイルクラスの実装はそのまま残された。新スタイルクラスを作成するためには、objectクラス(新スタイルクラス階層のルート)などの、既存の新スタイルクラスをただ継承するだけで行うことができる。

class A(object):
  実装
  ...

新スタイルクラスへの変更は大成功であった。新しく導入されたメタクラスは、フレームワーク作成者の中で人気の機能となったし、例外事項が減り、クラスを説明するのが簡単になった。実際、後方互換性は残されているため、新スタイルクラスの導入が行われても、古いコードは同じように動作させ続けることができた。最終的に、旧スタイルは言語から削除されることになると思うが、Pythonユーザは"class MyClass(object)"という、それほど悪くない書き方に、慣れてきている。

2009年5月1日金曜日

メタクラスとクラス拡張(通称:殺人ジョーク)

原文:http://python-history.blogspot.com/2009/04/metaclasses-and-extension-classes-aka.html
原文投稿者:Guido van Rossum

Pythonの最初の実装では、クラス自身もファーストクラスオブジェクトであり、変数に入れたり、関数の属性に渡したり、他のオブジェクトと同じように扱うことができた。しかし、クラスオブジェクトを作成するプロセスは、石版に刻まれた手順がごとく、変更することはできなかった。具体的に説明すると、以下のようなクラス定義があったとする。

class ClassName(BaseClass, ...):
     ...メソッド定義... 

クラスの本体は、新しく作られるローカル辞書の中で実行される。クラス名、ベースクラスが格納されたタプル、そしてこのローカル辞書の3つが内部のクラス作成関数に渡される。この関数が最終的にクラスオブジェクトを作成する責任を持っている。これらの工程は隠れて見えなかったが、そもそもユーザが心配する必要のない、実装の詳細にあたる部分であった。

Don Beaudry氏はエキスパートユーザのために、隠れた可能性を指摘した最初のユーザであった。具体的には、もしクラスそのものもシンプルで特別なオブジェクトであるならば、通常とは違う動作をする、新しい種類のクラスを作ることはできないのか?というものであった。彼はインタプリタにわずかな修正を加え、C言語のコードの拡張モジュールを使って、新しい種類クラスを作れるようにして、それを提案した。この変更が初めて紹介されたのは1995年であった。これは長い間、"Don Beaudryフック"もしくは"Don Beaudryハック"と呼ばれた。名前があいまいだったのはジョークだと思われていたからである。その後、Jim Fulton氏がその修正を一般化し、ドキュメントは不十分ではあったが、言語の一部にした。これは、Python 2.2で新スタイルクラスが導入されて、メタクラスの本当のサポートが始まるまでは、拡張可能なメカニズムとして言語に残っていた。これについては後で触れる。

Don Beaudryフックの基本的な考え方は、クラス作成の最終段階の中でカスタムクラスオブジェクトを作成する、というものであった。例えば、作成されたクラスに対して、ユーザの提供した関数を追加する、といったことが考えられた。具体的には、クラス名、ベースクラス、ローカル辞書の3つの情報を、通常とは異なるクラス作成関数に渡すことができれば、その関数はクラスオブジェクトを作成するための情報を使用してできることは何でもできるのである。唯一私が懸念していたのは、既に確立しているクラスの文法には変更を加えたくない、というものだけであった。

これを行うためには、当時はC言語で新しい型オブジェクトを作成し、呼び出し可能なオブジェクトとしてフックを作成する必要があった。そして、その呼び出し可能な型のインスタンスはクラス文のベースクラスとして使用され、そのクラスが標準のクラスオブジェクトを作成する代わりに、魔法のようにその型オブジェクトを呼び出されるようにするのである。呼び出し可能な型オブジェクトを提供する拡張モジュールを使用することで、クラス作成の振る舞いはこのように変更することができた。

最近のPythonユーザからすると、このようなハックは奇妙に思えるだろう。しかし、当時は型オブジェクトは呼び出し可能ではなかったのである。例えば、int型は組み込みの型ではなく、intオブジェクトを返す組み込み関数であった。int型自身は簡単にはアクセスできなかったし、呼び出すこともできなかった。ユーザ定義クラスもちろん呼び出し可能であったが、元々CALL命令を使ってオブジェクトを作成するというのは特殊なケースであり、組み込みの型はどれも、これとはまったく違う実装になっていた。Don Beaudry氏は最終的に、私の頭に最初のメタクラス、後の新スタイルクラスに繋がるアイディアを植え付け、最終的には古いクラスに引導を渡す役割を果たすことになった。

元々は、Don Beaudry氏自身が作成した、MESSという名前のPython拡張だけが、この機能を利用していた。しかし、1996年の末には、Jim Fulton氏は広く一般的になったExtension ClassesというサードパーティのパッケージをDon Beaundryフックを利用して開発した。Extension ClassesパッケージはPython 2.2がメタクラスをオブジェクト機構の標準の一部として導入して以降は、メリットがなくなった。

Python 1.5では、Don Beaudryフックを利用するために、C言語の拡張を作成しなければならないという制限が取り除かれた。これに加えて、呼び出し可能なベースクラス型のチェック機構を組み込み、"__calss__"という名前の属性をチェックも追加し、もしこの属性が存在していれば、クラス作成コードがこれを呼び出すようになった。私はこの機能についてのエッセーを書いた。これは多くのPythonユーザーにメタクラスのアイディアを紹介する、最初の文章となった。その文章には、頭を爆発させるようなアイディアが多く詰まっていたため、「殺人ジョーク」というニックネーム(モンティ・パイソン参照)がすぐについた。

Don Beaundryフックのもっとも偉大な功績は、クラス作成関数のAPIである。これはPython 2.2に持ち越され、メタクラス機構として実装された。前に説明したように、クラス作成関数は3つの引数を伴って呼び出される。クラス名の入った文字列。そしてベースクラスの入ったタプル(これは空でも、一つだけでも良い)、名前空間の中身が含まれている辞書である。この辞書にはメソッド定義や、その他のクラスレベルのコードが書かれたインデントブロックの内容が含まれる。クラス作成関数の返り値は、クラス名と同じ名前の変数に格納される。

当初は、これはただクラスを作成するためだけの内部APIでしかなかった。Don Beaudryフックは同じ呼び出し規約を使用するようになり、公開APIとなった。このAPIの見落とせないポイントは、メソッド定義が含まれるブロックはクラス作成関数が呼び出される前に定義されるということである。メタクラスはこの部分に対しては影響を与えることはできないため、メソッド定義が実行される名前空間の初期コンテンツに作用することはできないのである。

Python3000ではこの部分も変更され、メタクラスは通常とは異なるマッピングオブジェクトを提供し、その中でクラス本体の実行を行わせることができるようになる。これをサポートするために、明示的にメタクラス定義する文法も変更される。この目的のために、ベースクラスのリストの中でキーワード引数の文法を使用できるようになる。

訳注:メタクラスの文法は以下のように変更された

# Python 2.x
class C(object):
  __metaclass__ = M
  ...
# Python 3.x
class C(metaclass = M):
  ...

次のエピソードでは、メタクラスの考えが、いかにして2.2の新スタイルクラスの導入につながったのか、また、3.0の中で最終的に古い形式のクラスがどのように終局を迎えたか、ということについて、詳しく書きたいと思う。

ヘビ来襲!

原文:http://python-history.blogspot.com/2009/04/and-snake-attacks.html
原文投稿者:Greg Stein

1995年に私は初めてPythonと遭遇した。Pythonを"ヘビ"として言及することは禁止されている。Pythonは爬虫類の方ではなく、モンティ・パイソンにちなんで命名されたからである。 もし誰かがあなたを攻撃していたら、犯人はKnights who say NiかおそらくRabbit of Caerbannogである。

訳注:Knights who say Niは、モンティ・パイソンの2作目のコメディ映画である、モンティ・パイソン・アンド・ホーリー・グレイルに登場する、騎士のグループのこと。Rabbit of Caerbannogはその映画に登場する殺人ウサギ。

とにかく、1994には私はLPMUD(マルチユーザのRPG)の中でフィクション上の悪役と闘っていた。Webはかろうじて存在していたが、ブロードバンドという言葉は聞いたことがなく、バンド幅が少なくてすむゲームが一般的だった。

もう少し戻ろう。1979年。私が最初に触れたコンピュータはAppleⅡだった。当時のお気に入りのゲームの一つがColossal Caveであった。その後は、Zorkをプレイすることを覚えた。私はインタラクティブなフィクションというコンセプトと、これらのストーリーをコンピュータが制御しているということに心を奪われた。これらのゲームに捕まえられて、コンピュータのある生活がそこから始まった。(そう、25年以上して、Don Woods氏に会うことができたときの私の喜びは想像できるでしょうか?)

訳注:Don WoodsはColossal Caveの開発者

MUDをプレイするのはとても面白かったが、私はこれらのゲームの作成を手伝いたいと思うようになってきた。私はLPMUDのゲーム作家でコーダーで設計者でもあるJohn Viega氏に会った。そのとき彼はヴァージニア大学のコンピュータグラフィックスラボでAliceと呼ばれるシステムに関する仕事をしていた。このシステムはコンピュータに詳しくない人向けのシステムで、アニメーションを作成したい人向けに学びやすい言語を必要としていた。彼らは明快さ、パワー、シンプルさからPythonを選択した。

John氏はPythonの熱烈なファンで、私にPythonを紹介して「これだけは覚えて下さい!」「いいよ、いいよ」という会話した。その言語は簡単だがパワフルで、苦労しなくても何でもできた。

それが1995年の2月。私はまだそこから戻ってきていない。

そのときはあまり思っていなかったが、その後の私の仕事と人生にとって、Pythonは重要な軸となった。Guido氏の作品に感謝したいと思います。