tag:blogger.com,1999:blog-60182598592202189482024-02-21T04:46:14.759+09:00The History of Python.jpプログラミング言語Pythonと、そのコミュニティをめぐる文書集ですSHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.comBlogger26125tag:blogger.com,1999:blog-6018259859220218948.post-18577080497265816842010-09-21T00:44:00.005+09:002010-09-21T09:50:02.505+09:00なぜPythonの割り算はC言語と違う方式なのか?<!--I was asked (again) today to explain why integer division in Python returns the floor of
the result instead of truncating towards zero like C.-->
<p>今日は何度も「なぜPythonの整数の割り算はC言語のようにゼロに向けて丸めるのではなく、切り捨てなのか?」と聞かれた。</p>
<!--For positive numbers, there's no surprise:-->
<p>数値が両方とも正の場合には、何も驚くようなことは発生しない。</p>
<pre name="code" class="python">>>> 5//2
2</pre>
<!--But if one of the operands is negative, the result is floored, i.e., rounded away from
zero (towards negative infinity):-->
<p>しかし、どちらかの数値が負の場合、結果は切り捨てられる。言い換えると、ゼロから遠い方向(負の無限大方向)に向けて丸められる。</p>
<pre name="code" class="python">>>> -5//2
-3
>>> 5//-2
-3</pre>
<!--This disturbs some people, but there is a good mathematical reason. The integer division
operation (//) and its sibling, the modulo operation (%), go together and satisfy a nice
mathematical relationship (all variables are integers):-->
<p>この挙動は何人かの人を混乱させたようであるが、このような実装になっているのは数学的な根拠がある。整数の割り算の演算子(//)と、その弟の余りを計算する演算子(%)は、次のような数学的な関係を保っている。すべての変数は整数とする。</p>
<!--a/b = q with remainder r-->
<pre name="code" class="python">a/b = q あまり r</pre>
<!--such that-->
<p>これは、次のような関係性を持っている。</p>
<!--b*q + r = a and 0 <= r < b-->
<!--(assuming a and b are >= 0).-->
<pre name="code" class="python">b * q + r = a かつ 0 <= r < b
(ただし、a, bはともに0以上の整数)</pre>
<!--If you want the relationship to extend for negative a (keeping b positive), you have two
choices: if you truncate q towards zero, r will become negative, so that the invariant
changes to 0 <= abs(r) < otherwise, you can floor q towards negative infinity, and the
invariant remains 0 <= r < b. [update: fixed this para]-->
<p>もしも、この式の関係性を、負の数値まで拡張したいのであれば、2つの選択肢があります。もし商をゼロに向けて丸めるのであれば、付帯条件を<tt>0 <= abs(r)</tt>と変更する必要がある。それ以外には、qを負の無限大の方に向けて丸める方法がある。この場合、付帯条件は<tt>0 <= r < b</tt>のままである。</p>
<!--In mathematical number theory, mathematicians always prefer the latter choice (see e.g.
Wikipedia). For Python, I made the same choice because there are some interesting applications
of the modulo operation where the sign of a is uninteresting. Consider taking a POSIX
timestamp (seconds since the start of 1970) and turning it into the time of day. Since
there are 24*3600 = 86400 seconds in a day, this calculation is simply t % 86400. But if
we were to express times before 1970 using negative numbers, the "truncate towards zero"
rule would give a meaningless result! Using the floor rule it all works out fine.-->
<p>数学の整数論を考えると、数学者はいつも後者の選択を望ましいと考えてきた(<a href="http://en.wikipedia.org/wiki/Modulo_operation">Wikipedia</a>参照)。この方式の割り算が役に立つ、おもしろい利用方法がいくつかあったので、Pythonでもこの後者の挙動を採用した。POSIXのタイムスタンプ(1970年からの経過の秒数)を取得して、時刻に変える、という場面を考えてみる。1日は24時間なので、24 * 3600 = 86400秒ある。これを計算するには、単に<tt>t % 86400</tt>とやれば良い。しかし、1970年依存のより前の時刻を計算したいと考えると、ゼロ方向に丸めてしまうと、無意味な結果が帰ってくることになる。負の無限大方向に丸めるというルールであれば、このような場面でも、そのまま適用できる。</p>
<!--Other applications I've though of are computations of pixel positions in computer
graphics. I'm sure there are more.-->
<p>コンピュータグラフィックスで、ピクセルの位置を計算する場面でも、同じ事が言える。こちらの方が良く発生するだろう。</p>
<!--For negative b, by the way, everything just flips, and the invariant becomes:-->
<p>もしbが負の値をであれば、すべてが逆さまになる。普遍条件は次のようになる。</p>
<pre name="code" class="python">0 >= r > b.</pre>
<!--So why doesn't C do it this way? Probably the hardware didn't do this at the time
C was designed. And the hardware probably didn't do it this way because in the
oldest hardware, negative numbers were represented as "sign + magnitude" rather
than the two's complement representation used these days (at least for integers).
My first computer was a Control Data mainframe and it used one's complement for
integers as well as floats. A pattern of 60 ones meant negative zero!-->
<p>それでは、なぜC言語はこのような実装になっていないのだろうか?それは、Cが設計された当時のハードウェアがこのようにしていなかったからである。そして、現在では負の数は補数として表現されているが、当時のコンピュータは少なくとも整数に関しては、「符号+大きさ」という表現になっていた。私が最初に触れたコンピュータはデータを制御するメインフレームであったが、浮動小数点数と同じく、整数に補数を使うようになっていた。そのハードは負のゼロを表すパターンが60個もあったのである!</p>
<!--Tim Peters, who knows where all Python's floating point skeletons are buried, has
expressed some worry about my desire to extend these rules to floating point modulo.
He's probably right; the truncate-towards-negative-infinity rule can cause precision
loss for x%1.0 when x is a very small negative number. But that's not enough for
me to break integer modulo, and // is tightly coupled to that.-->
<p>Pythonの浮動小数点数を完全に知り尽くしているTim Petersは、これらの規則を浮動小数点数の割り算にも広げたいという私の願望に対して、いくつか心配に思っていることを説明してくれた。彼の心配は正しかった。負の無限大の方向に丸めるというルールは、<tt>x%1.0</tt>という式があったときに、xが非常に小さい負の整数の時に精度が失われてしまうのである。しかし、これは整数の割り算を破壊するものではなく、<tt>//</tt>はそれに密に結合されている。</tt></p>
<!--PS. Note that I am using // instead of / -- this is Python 3 syntax, and also
allowed in Python 2 to emphasize that you know you are invoking integer division.
The / operator in Python 2 is ambiguous, since it returns a different result for
two integer operands than for an int and a float or two floats. But that's a totally
separate story; see PEP 238.-->
<p>PS. 上記の説明では、<tt>/</tt>の代わりに<tt>//</tt>を使用した。これはPython 3の文法で、Python 2でも割り算が整数領域で行われるのを強調したいときに利用できる。Python 2の<tt>/</tt>演算子は、演算する数が両方整数か、一つ以上浮動小数点数が含まれているかで型が変わるという曖昧なところがある。しかし、これに関してはまったく別の話なので、ここでは説明しない。詳しくは<a href="http://www.python.org/dev/peps/pep-0238/">PEP 238</a>に書かれている。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-75283629774073491052010-09-08T19:28:00.005+09:002010-09-09T07:18:38.416+09:00リスト内包表記〜ジェネレータ式<!--List comprehensions were added in Python 2.0. This feature originated
as a set of patches by Greg Ewing with contributions by Skip Montanaro and
Thomas Wouters. (IIRC Tim Peters also strongly endorsed the idea.)
Essentially, they are a Pythonic interpretation of a well-known notation
for sets used by mathematicians. For example, it is commonly understood
that this:-->
<p>リスト内包表記はPython 2.0で追加された。この機能はGreg Ewingによるパッチを元にして、Skip MontanaroとThomas Woutersらの貢献もあって実現された。私の記憶が正しければ、Tim Petersもこのアイディアをしっかりと保証してくれた。基本的には、リスト内包表記は数学者によって使用されてきた、よく知られた表記法をPythonicに解釈して実現したものである。</p>
<pre name="code" class="python">{x | x > 10}</pre>
<!--refers to the set of all x such that x > 10. In math, this form implies
a universal set that is understood by the reader (for example, the set of
all reals, or the set of all integers, depending on the context). In
Python, there is no concept of a universal set, and in Python 2.0, there
were no sets. (Sets are an interesting story, of which more in a future
blog post.)-->
<p>これは、一般に、10より大きな数の集合と解釈される。数学の世界では、この形式は、例えば全ての実数、全ての整数などを表す普遍集合(universal set)であると、読み手は解釈する。Pythonの2.0には普遍集合の概念はなく、setもなかった。setについてもおもしろい話があるため、将来ブログに投稿することになるだろう。</p>
<!--This and other considerations led to the following notation in
Python:-->
<p>この概念や、他の状況も踏まえ、次のようなPython流の表記が作られた:</p>
<pre name="code" class="python">[f(x) for x in S if P(x)]</pre>
<!--This produces a list containing the values of the sequence S selected
by the predicate P and mapped by the function f. The if-clause is optional,
and multiple for-clauses may be present, each with their own optional
if-clause, to represent nested loops (the latter feature is rarely used
though, since it typically maps a multi-dimensional entity to a
one-dimensional list).-->
<p>これを実行すると、シーケンスSに含まれる値のうち、述部Pの評価結果に合う要素に対して、関数fを適用した結果を含むリストが生成される。if節はオプションとなっているし、また、for節を複数入れて、それぞれにif節を書いて、ネストされたループを表現することもできる。ただし、このネストされたループはあまり使われることはない。一般的には多次元の要素を、1次元のリストにマップすることが良く行われる。</p>
<!--List comprehensions provide an alternative to using the built-in map()
and filter() functions. map(f, S) is equivalent to [f(x) for x in S] while
filter(P, S) is equivalent to [x for x in S if P(x)]. One would think that
list comprehensions have little to recommend themselves over the seemingly
more compact map() and filter() notations. However, the picture changes if
one looks at a more realistic example. Suppose we want to add 1 to the
elements of a list, producing a new list. The list comprehension solution
is [x+1 for x in S]. The solution using map() is map(lambda x: x+1, S). The
part “lambda x: x+1” is Python’s notation for an anonymous function defined
in-line.-->
<p>リスト内包表記は、組み込み関数の<tt>map()</tt>と<tt>filter()</tt>の代替手段となっている。<tt>map(f, S)</tt>は、<tt>[f(x) for x in S]</tt>と同じ意味となるし、<tt>filter(P, S)</tt>は<tt>[x for x in S if P(x)]</tt>と同じ意味となる。<tt>map()</tt>や<tt>filter()</tt>を使った表現の方がコンパクトであるため、リスト内包表記の方が推奨されていないのでは?と思う人もいるだろう。しかし、より現実的なサンプルを見ると見解が変わるだろう。与えられたリストの全ての要素に数字の1が足された、新しいリストを作りたいとする。リスト内包表記を使った場合には、<tt>[x+1 for x in S]</tt>と表現できる。<tt>map()</tt>を使うと、<tt>map(lambda x: x+1, S)</tt>となる。<tt>"lambda x: x+1"</tt>はインラインで無名関数を作るPythonの書き方である。</p>
<!--It has been argued that the real problem here is that Python’s lambda
notation is too verbose, and that a more concise notation for anonymous
functions would make map() more attractive. Personally, I disagree?I find
the list comprehension notation much easier to read than the functional
notation, especially as the complexity of the expression to be mapped
increases. In addition, the list comprehension executes much faster than
the solution using map and lambda. This is because calling a lambda
function creates a new stack frame while the expression in the list
comprehension is evaluated without creating a new stack frame.-->
<p>ここでの本当の問題はPythonのラムダ記法が冗長すぎることで、この表記がもっと簡潔になれば<tt>map()</tt>を使った記法がより魅力的になるはずだ、ということがずっと主張されてきた。私個人の見解としてはこれには反対である。リスト内包表記の方が、特にマップされる式の複雑さが増加すると<tt>map()</tt>を使った関数表記よりも見やすくなることが分かったからである。それに加えて、リスト内包表記を使った方が、実行速度の面からも、<tt>map()</tt>とラムダを使うよりも高速である。内部的に、ラムダ関数の呼び出し時には新しいスタックフレームが作られるオーバーヘッドがあるが、リスト内包表記の評価時には新しいスタックフレームが作られないからである。</p>
<!--Given the success of list comprehensions, and enabled by the invention
of generators (of which more in a future episode), Python 2.4 added a
similar notation that represents a sequence of results without turning it
into a concrete list. The new feature is called a “generator expression”.
For example:-->
<p>リスト内包表記の成功を受けて、Python 2.4からは似たような表記であるが、実際にリストを生成せずにシーケンスを表現できる、ジェネレータ(これについては将来のエントリーで紹介する)が発明されることになった。この機能は「ジェネレータ式」と呼ばれる。</p>
<pre name="code" class="python">sum(x**2 for x in range(1, 11))</pre>
<!--This calls the built-in function sum() with as its argument a generator
expression that yields the squares of the numbers from 1 through 10
inclusive. The sum() function adds up the values in its argument resulting
in an answer of 385. The advantage over sum([x**2 for x in range(1, 11)])
should be obvious. The latter creates a list containing all the squares,
which is then iterated over once before it is thrown away. For large
collections these savings in memory usage are an important
consideration.-->
<p>これは、引数にジェネレータ表現の引数を使用して、組み込みの<tt>sum()</tt>関数が呼ばれている。このジェネレータは、1から10までの数値の数の2乗を生成する。この関数は引数で生成された値をすべて合計して、385を返す。<tt>sum([x**2 for x in range(1, 11)])</tt>という表記と比べると、メリットは明らかである。リスト内包表記を使うと、すべての2乗の数を含むリストが実際に生成され、一度使われて破棄されてしまうのである。メモリ使用量が大きくなる巨大な配列の場合には、これも考慮すべきである。</p>
<!--I should add that the differences between list comprehensions and
generator expressions are fairly subtle. For example, in Python 2, this is
a valid list comprehension:-->
<p>リスト内包表記と、ジェネレータ表現の違いは小さいということも説明すべきだろう。例えば、Python 2では、次の表現は有効なリスト内包表記である。</p>
<pre name="code" class="python">[x**2 for x in 1, 2, 3]</pre>
<!--However this is not a valid generator expression:-->
<p>しかし、次の表現はジェネレータ表現としては有効ではない。</p>
<pre name="code" class="python">(x**2 for x in 1, 2, 3)</pre>
<!--We can fix it by adding parentheses around the "1, 2, 3" part:-->
<p>"1, 2, 3"の部分にカッコを付けることで、きちんと動作させることができる。</p>
<pre name="code" class="python">(x**2 for x in (1, 2, 3))</pre>
<!--In Python 3, you also have to use these parentheses for the list
comprehension:-->
<p>Python 3では、これらのカッコは、リスト内包表記でも付ける必要がある。</p>
<pre name="code" class="python">[x**2 for x in (1, 2, 3)]</pre>
<!--However, in a "regular" or "explicit" for-loop, you can still omit
them:-->
<p>しかし、通常のforループや、明示的なforループの場合にはこれをキャンセルすることもできる。</p>
<pre name="code" class="python">for x in 1, 2, 3: print(x**2)</pre>
<!--Why the differences, and why the changes to a more restrictive list
comprehension in Python 3? The factors affecting the design were backwards
compatibility, avoiding ambiguity, the desire for equivalence, and
evolution of the language. Originally, Python (before it even had a version
:-) only had the explicit for-loop. There is no ambiguity here for the part
that comes after 'in': it is always followed by a colon. Therefore, I
figured that if you wanted to loop over a bunch of known values, you
shouldn't be bothered with having to put parentheses around them. This also
reminded me of Algol-60, where you can write:-->
<p>なぜ違いがあるのか、なぜPython 3.0ではリスト内包表記が厳格化されたのか?設計に影響を与えた要因としては、後方互換性、あいまいさの排除、等価性、言語の進化がある。初めPythonには、明示的なforループしかなかった。この場合には、<tt>'in'</tt>の後ろから、コロン(:)の前までであったため、あいまいなところはなかった。そのため、既知の値の上でループを回したいのであれば、煩わしくカッコを付ける必要はない。これを見ると、次のように書けた、Algol-60が思い出される。</p>
<pre name="code" class="python">for i := 1, 2, 3 do Statement</pre>
<!--except that in Algol-60 you can also replace each expression with
step-until clause, like this:-->
<p>Algol-60はそれぞれの式の中に、step-until構文を利用することもできる。</p>
<pre name="code" class="python">for i := 1 step 1 until 10, 12 step 2 until
50, 55 step 5 until 100 do Statement</pre>
<!--(In retrospect it would have been cool if Python for-loops had the
ability to iterate over multiple sequences as well. Alas...)-->
<p>(これを振り返ると、Pythonのforループも、複数のシーケンス上でループが回せていたらもっとクールだっただろう)</p>
<!--When we added list comprehensions in Python 2.0, the same reasoning
applied: the sequence expression could only be followed by a close bracket
']' or by a 'for' or 'if' keyword. And it was good.-->
<p>Python 2.0にリスト内包表記を追加したときにも同じような推測法を適用した。シーケンスの式の後ろには閉じたブラケット']'、もしくは'for', 'if'キーワードのみが来るため問題が発生することはなかった。</p>
<!--But when we added generator expressions in Python 2.4, we ran into a
problem with ambiguity: the parentheses around a generator expression are
not technically part of the generator expression syntax. For example, in
this example:-->
<p>しかし、ジェネレータ式が2.4で追加されると、あいまいさの問題が頭をもたげてきた。ジェネレータ式のまわりのカッコは、ジェネレータ式の一部ではないことも技術的にありえるからだ。次の例を見てみよう。</p>
<pre name="code" class="python">sum(x**2 for x in range(10))</pre>
<!--the outer parentheses are part of the call to sum(), and a "bare"
generator expression occurs as the first argument. So in theory there would
be two interpretations for something like this:-->
<p>外部のカッコは、sum()関数の呼び出しの一部であり、「裸の」ジェネレータ式が最初の引数として渡される。そのため、理論的には次の式は2通りの理解の仕方がある。</p>
<pre name="code" class="python">sum(x**2 for x in a, b)</pre>
<!--This could either be intended as:-->
<p>これは、次の文を意図したものである。</p>
<pre name="code" class="python">sum(x**2 for x in (a, b))</pre>
<!--or as:-->
<p>このようにも理解できる。</p>
<pre name="code" class="python">sum((x**2 for x in a), b)</pre>
<!--After a lot of hemming and hawing (IIRC) we decided not to guess in
this case, and the generator comprehension was required to have a single
expression (evaluating to an iterable, of course) after its 'in' keyword.
But at the time we didn't want to break existing code using the (already
hugely popular) list comprehensions.-->
<p>その後、活発な議論が行われ、(私の記憶が正しければ)このような場合には推測をしない、ジェネレータ内包表記の場合には、'<tt>in</tt>'キーワードの後ろには単一の式(もちろん繰り返し可能)を必要とする、ということになった。既に人気のある構文となっていた、リスト内包表記を使用していた既存のコードの互換性を崩したくない、という考えもあった。</p>
<!--Then when we were designing Python 3, we decided that we wanted the
list comprehension:-->
<p>Python 3の設計をしている時にリスト内包表記の動作に変更を加えた。次のようなリスト内包表記があったとすると、</p>
<pre name="code" class="python">[f(x) for x in S if P(x)]</pre>
<!--to be fully equivalent to the following expansion using the built-in
list() function applied to a generator expression:-->
<p>組み込みの<tt>list()</tt>関数をジェネレータ式に適用した、次の文と同一になるようにした。</p>
<pre name="code" class="python">list(f(x) for x in S if P(x))</pre>
<!--Thus we decided to use the slightly more restrictive syntax of
generator expressions for list comprehensions as well.-->
<p>このため、リスト内包表記でも、多少制約の強い、ジェネレータ式の構文を使用することを決定した。</p>
<!--We also made another change in Python 3, to improve equivalence between
list comprehensions and generator expressions. In Python 2, the list
comprehension "leaks" the loop control variable into the surrounding
scope:-->
<p>Python 3ではもう一つ変更を加え、リスト内包表記とジェネレータ式の等価性が向上した。Python 2では、リスト内包表記のループ制御変数は周辺のスコープに「漏れ」ていた。</p>
<pre name="code" class="python">x = 'before'
a = [x for x in 1, 2, 3]
print x # this prints '3', not 'before'</pre>
<!--This was an artifact of the original implementation of list
comprehensions; it was one of Python's "dirty little secrets" for years. It
started out as an intentional compromise to make list comprehensions
blindingly fast, and while it was not a common pitfall for beginners, it
definitely stung people occasionally. For generator expressions we could
not do this. Generator expressions are implemented using generators, whose
execution requires a separate execution frame. Thus, generator expressions
(especially if they iterate over a short sequence) were less efficient than
list comprehensions.-->
<p>これは、リスト内包表記の元本の実装によってもたらされた副作用である。これは昔からある、Pythonの「隠しておきたい小さな汚点」の一つであった。意図的な妥協のおかげで、リスト内包表記は最初から高速な実装であった。初心者がひっかかるような落とし穴ではなかったが、時々害を受ける人が出た。ジェネレータ式の実行には別の実行フレームが必要とされるため、ジェネレータ式では同じようなことはできなかった。そのため、特に小さなシーケンスを相手にする場合には、効率性の面でジェネレータ式はリスト内包表記に負けていた。</p>
<!--However, in Python 3, we decided to fix the "dirty little secret" of
list comprehensions by using the same implementation strategy as for
generator expressions. Thus, in Python 3, the above example (after
modification to use print(x) :-) will print 'before', proving that the 'x'
in the list comprehension temporarily shadows but does not override the 'x'
in the surrounding scope.-->
<p>しかし、Python 3では、我々はジェネレータ式と同じ実装の戦略を取ることで、リスト内包表記の「隠しておきたい小さな汚点」を修正することを決定した。そのため、Python 3で上記のサンプルを実行すると(<tt>print(x)</tt>と変更を加えましょう :-)、<tt>'before'</tt>と表示され、リスト内包表記で一時的に隠された変数'<tt>x</tt>'も、周囲のスコープの'<tt>x</tt>'を上書きしないということが分かるだろう。</p>
<!--And before you start worrying about list comprehensions becoming slow
in Python 3: thanks to the enormous implementation effort that went into
Python 3 to speed things up in general, both list comprehensions and
generator expressions in Python 3 are actually faster than they were in
Python 2! (And there is no longer a speed difference between the two.)-->
<p>これによって、Python 3のリスト内包表記は遅くなったのではないか、と心配する人もいると思うが、Python 3を高速化しようという膨大な努力のおかげで、Python 3のリスト内包表記と、ジェネレータ式は、Python 2と比較してそれぞれ高速になっている。また、この2つの間にあった速度差も解消している。</p>
<!--UPDATE: Of course, I forgot to mention that Python 3 also supports set
comprehensions and dictionary comprehensions. These are straightforward
extensions of the list comprehension idea.-->
<p><b>更新:</b> Python 3で追加された、setとdictの内包表記について言及するのを忘れていた。これらは、リスト内包表記を素直に拡張しただけである。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com1tag:blogger.com,1999:blog-6018259859220218948.post-63018832857914382692010-08-01T15:52:00.002+09:002010-08-01T16:30:15.244+09:00メソッド解決順序(MRO)<p>多重継承が利用可能な言語では、メソッドを探索するときのベースクラスを探索する順序を、メソッド解決順序(MRO)と呼んでいる。Pythonではメソッドだけではなく、属性の探索でもこれが利用される。単一継承しかサポートしていない言語では、MROはとてもつまらない話題であるが、多重継承の場合には必要となってきて、MROアルゴリズムの選択が極めて難しい問題となりうる。Pythonでは、クラシック、Python 2.2の新スタイル、Python 2.3の新スタイル(C3とも呼ばれる)の3種類のMROアルゴリズムを持っていることが知られている。Python 3では、最後のアルゴリズムだけが生き残っている。</p>
<p>旧スタイルクラスはシンプルなMROの方式を利用していた。メソッドを探す場合には、シンプルに深さ優先探索を行って、ベースクラスの中で最初にマッチしたオブジェクトが返される。例えば、次のようなクラス構造について見てみよう。</p>
<pre name="code" class="python">class A:
def save(self): pass
class B(A): pass
class C:
def save(self): pass
class D(B, C): pass
</pre>
<p>クラスDのインスタンスxを作ったとすると、クラシック方式のメソッド解決順序では、D, B, A, Cという順序でクラスが探索されることとなる。そのため、<tt>x.save()</tt>というメソッド呼び出しが行われると、<tt>C.save()</tt>ではなく、<tt>A.save()</tt>が実行される。この方式は単純なケースではうまく行くが、より複雑なケースでは問題が発生してくる。次のような、ダイアモンド継承下でのメソッド検索の問題について見てみよう。</p>
<pre name="code" class="python">class A:
def save(self): pass
class B(A): pass
class C(A):
def save(self): pass
class D(B, C): pass
</pre>
<p>ここでは、クラスDはBとCを継承しており、その両方ともがクラスAを継承している。クラシックMROを使うと、D, B, A, C, Aという順序でメソッドを探索していくため、<tt>x.save()</tt>は、<tt>A.save()</tt>を参照する。しかし、この場合は、あなたが期待するのと違っているはずだ。BとCの両方がAを継承しており、再定義されてクラスAよりも詳細化された<tt>C.save()</tt>を、クラスAのメソッドよりも呼びたいと考える人もいるだろう。実際は<tt>A.save()</tt>が常に呼ばれる。例えば、<tt>save()</tt>メソッドがオブジェクトの状態の保存に使用されるのであれば、クラスCによって定義されたメソッドが呼ばれないことで、Cに関する状態が無視されてプログラムの動作に問題が生じる。</p>
<p>この種の多重継承は、既存のコードの中でもめったに使われていないが、新スタイルクラスを使うとこの問題が日常茶飯事となる。新スタイルクラスはベースクラスであるobjectを継承することで行われる。新スタイルクラスでは、どのように多重継承を行っても、必ず上記のようなダイアモンド継承状態になる。</p>
<pre name="code" class="python">class B(object): pass
class C(object):
def __setattr__(self, name, value): pass
class D(B, C): pass
</pre>
<p>それに加えて、派生クラスで拡張されるような(<tt>__setattr__()</tt>など)、いくつかのメソッドをobjectクラスが持っているため、このメソッドの解決順序の重要性は以前よりも高くなった。例えば、上記のコードの場合には、<tt>C.__setattr__</tt>は、クラスDのインスタンスにも適用されるべきである。</p>
<p>Python 2.2では、新スタイルクラスの導入のためにメソッド解決順序の見直しを行い、クラス定義時にあらかじめ順序を計算しておき、クラスオブジェクトごとに属性として格納するという方式のMROを適用した。以前の公式ドキュメントでは、深さ優先探索のMROを利用していると書かれていた。この検索順序の中で同じクラスが重複すると、MROのリストの中で後半に出てきた方が削除されるようになった。そのため、前に挙げたサンプルでは、D, B, C, Aという順序になり、以前のクラシッククラスで説明したD, B, A, C, Aとは違う結果になる。</p>
<p>実際には、MROの計算はこれよりもはるかに複雑である。私は、この新しいMROアルゴリズムがうまく働かないようなケースをいくつか発見した。2つのベースクラス(A, B)が、2つの異なる派生クラス(X, Y)のMROのリストの中でそれぞれ異なる順序で並ぶという特殊なケースがある。これらのクラスは元のクラスをそれぞれ異なる順序で継承しており、さらにそれを他のクラス(Z)が継承している。</p>
<pre name="code" class="python">class A:
class A(object): pass
class B(object): pass
class X(A, B): pass
class Y(B, A): pass
class Z(X, Y): pass
</pre>
<p>試しにこの新しいMROアルゴリズムを使用してみると、これらのクラスのMROは、Z, X, Y, B, A, objectという順序に並ぶ。objectというのは、共通のベースクラスである。しかし、私はBとAが逆になっているというのが気に入らなかった。本当のMROは、それらの順番を入れ替えて、Z, X, Y, A, B, objectという順番にする。このアルゴリズムは最初に検索したときに見つかった順番をなるべく保存しようとする。クラスZの場合には、継承リストの順番が先ということで、ベースクラスXが先に検索される。XはAとBを継承しているため、MROアルゴリズムはこの順番を保存しようとする。これはPython 2.2で実装されたもので、初期のアルゴリズムとしてドキュメント化した。</p>
<p>しかし、Python 2.2で新スタイルクラスが導入されてすぐに、Samuel Pedroni氏は、このドキュメント化されたMROアルゴリズムと、実際にコードを動かした結果が異なるということを発見した。さらに、これらの矛盾は上記のような特別な場合以外でも発生していた。長い時間をかけて議論を行い、Python 2.2で採用されたMROは壊れていることが確認され、"A Monotonic Superclass Linearization for Dylan" (K. Barrett, et al, presented at OOPSLA'96) で説明されている、C3線形化アルゴリズムを採用することが決定された。</p>
<p>本質的には、Python 2.2のMROアルゴリズムの本質的な問題は、探索順を線形に並べるという問題に関係していた。継承階層が複雑になると、それぞれの継承の関係は、シンプルなルールでクラスがどのような順番に並ぶかのチェックが行われる。明らかに、クラスAがクラスBを継承している場合にはMROはAがBの前にあることをチェックしなければならない。同様に、クラスBがクラスCとDを多重継承している場合には、BはCの前にあり、CはDの前にあることがチェックされなければならない。</p>
<p>複雑な継承階層の中では、順番を線形化する場合に、これらのルールをすべて満足するようにしたいと思うだろう。つまり、クラスAがクラスBの前になければならないということが決められた場合に、クラスBの方がクラスAの前に来るという矛盾した状態にはなって欲しくはない。その場合には結果が未定義なので、そのような継承階層はリジェクトされなければならない。オリジナルのMROが間違っていて、C3アルゴリズムがうまくいくのはこのような場面である。基本的に、C3の背後にあるアイディアは、複雑なクラス継承を行ったときにも、継承の関係から作られた順番のルールをすべてリストアップした場合に、すべてのクラス間でこれらのルールを満足するようなクラスの順番に、一列に並べることができるというものである。もしも、順番が一意に決まらない場合には、このアルゴリズムはその継承をエラーとして失敗させるようになっている。</p>
<p>そのため、Python 2.3では、Python 2.2で自前作ったMROアルゴリズムを捨て、アカデミックな目でチェックされたC3アルゴリズムを選択することにした。これにより、矛盾した順序を持つ継承を行うと、Pythonがそれをエラーとするようになった。例えば、先ほどの例で言えば、クラスXとクラスYの間では、順序に矛盾がある。クラスXを見るとクラスBの前にクラスAがなければならないということになるが、クラスYを見ると、クラスAの前にクラスBがなければならないことになっている。個別に見れば、これらの矛盾は問題ないが、これらのクラスXとYが、同じ継承階層の中に現れる(例えば、ここではクラスZが定義されることによってこれが発生する)と、C3アルゴリズムはこのクラスをリジェクトする。これは言うまでもなく、Pythonのthe Zen of Pythonの「問題があるときには、こっそりと処理してはならない」というルールにもマッチしている。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-33261204145989636702010-07-17T01:17:00.004+09:002010-07-17T01:50:43.785+09:00import antigravity<p>原文:<a href="http://python-history.blogspot.com/2010/06/import-antigravity.html">http://python-history.blogspot.com/2010/06/import-antigravity.html</a><br/>
原文投稿者:Guido van Rossum</p>
<!--The antigravity module, referencing the XKCD comic mentioning Python, was added to Python 3 by Skip Montanaro. You can read more about it here, one of the first spottings that I know of: http://sciyoshi.com/blog/2008/dec/30/import-antigravity/).-->
<p><a href="http://xkcd.com/353/">Pythonについて説明をしているXKCDコミック</a>を参照するというantigravityモジュールが、Skip MontanaroによってPython 3に追加された。私が知る限り最初にこのモジュールについて焦点をあてたブログはこれである: <a href="http://sciyoshi.com/blog/2008/dec/30/import-antigravity/">http://sciyoshi.com/blog/2008/dec/30/import-antigravity/</a></p>
<!--But it really originated in Google App Engine! It was a last-minute addition when we launched App Engine on April 7, 2008. A few weeks before launch, when most code was already frozen, the App Engine team at Google decided we wanted an easter egg. After a great many suggestions, some too complex, some too obscure, some too risky, we chose the "antigravity" module. The App Engine version is a little more elaborate than the Python 3 version: it defines a fly() function while can randomly do one of two things: with a probability of 10%, it redirects to the XKCD comic; otherwise, it simply renders the text of the comic in HTML (with a link to the comic on the last line). To invoke it in your App Engine app, you'd have to write a little main program, like this:-->
<p>しかし、このモジュールの本当の起源はGoogle App Engineである。私たち(訳注: GuidoはGoogleで働いている)がApp Engineを公開した、2008年4月7日の直前だった。公開の数週間前の、ほとんどのコードがコードフリーズしたときに、GoogleのApp Engineチームは何かイースターエッグを忍び込ませたいと考えた。時には複雑で、時にはあいまいで、時にはリスキーな、何度にも渡るすばらしい議論の末に、"antigravity"モジュールが選択された。App Engine版はPython 3版よりも多少がんばった作りになっている。App Engine版では、fly()関数が定義されていて、次の2つのうちの一方の動作をランダムにランダムに行う。1つ目は10%の確率で発生するモノで、XKCDのコミックにリダイレクトでジャンプする。もう一方はHTML内に、テキスト版のコミックを単純に書き出すだけのものである(最後の行にコミックへのリンクが表示される)。次のようなmain()プログラムを作成すると、App Engineのアプリケーション内でこれを呼び出すことができる。</p>
<pre name="code" class="python">
import antigravity
def main():
antigravity.fly()
if __name__ == '__main__':
main()
</pre>
<!--Update: The Python 3 stdlib version has an easter egg inside the easter egg, if you inspect the source code: it defines a function that purports to implement the XKCD geohashing algorithm.-->
<p><b>[更新情報]</b> Python 3の標準ライブラリ版では、ソースコードの中を見てみると、イースターエッグの中にさらにイースターエッグが仕込まれている。<a href="http://xkcd.com/426/">XKCDのgeohashアルゴリズム</a>について説明している関数が定義されている。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-21506725711463794252010-07-13T03:09:00.004+09:002010-07-13T08:31:58.988+09:00import thisとThe Zen of Python(2)<p>原文:<a href="http://www.wefearchange.org/2010/06/import-this-and-zen-of-python.html">http://www.wefearchange.org/2010/06/import-this-and-zen-of-python.html</a><br/>
原文投稿者:Barry Warsaw</p>
<p>注:本エントリーは、Guidoのブログではなく、そこで紹介されていた、Barry Warsaw氏のブログの翻訳です。翻訳と公開の許可をしてくださったBarry Warsaw氏に感謝します</p>
<!--Richard Jones is working on a talk for PyCon Australia and asked me about
the history of the Zen of Python, Tim Peters' eternal words of wisdom,
often quoted, on the essential truths of Python. At first, I couldn't find
a reference to the first publication of this list, but then I did a better
search of my archives and found that it was originally sent to the
python-list mailing list on June 4, 1999, under the subject "The Python
Way".-->
<p><a href="http://www.mechanicalcat.net/richard/log/Python">Richard Jones氏</a>は現在(元記事執筆時点)、<a href="http://pycon-au.org/2010/about/">PyCon Australia</a>でする話の準備をしている。彼はその準備の中で、私に"<a href="http://www.python.org/dev/peps/pep-0020/">Zen of Python</a>"の歴史についてたずねてきた。それはTim PetersがPython界に永遠に残した言葉で、Pythonの本質的な真実を良く伝えるものであり、さまざまな場面で引用されている。最初に調べたときには、このリストが最初に公表された時の情報を探すことはできなかったが、その後、自分のメールのアーカイブをすみずみまで調べたところ、"Zen of Python"が最初に<a href="http://mail.python.org/mailman/listinfo/python-list">Python-list</a>というメーリングリストに投稿された時のメールを見つけることができた。"The Python Way"というタイトルで、<a href="http://mail.python.org/pipermail/python-list/1999-June/616160.html">1999年の7月4日</a>に投稿されたものであった。</p>
<!--Interestingly enough, because I couldn't find that first reference
immediately, I went back into my archives and researched the "this" module.
Did you know that if you type the following at a modern Python interpreter,
you get the Zen of Python?-->
<p>すぐに最初の出典を見つけることができなかったので、自分のアーカイブの探査に戻ったり、"<a href="http://svn.python.org/view/python/tags/r221/Lib/this.py?revision=25249&view=markup">this</a>"モジュールの解析を行っていた。最近のPythonのインタプリタでは、次のようにタイプすると、"Zen of Python"を読むことができるというのをご存知だろうか?(訳注:日本語訳は<a href="http://python-history-jp.blogspot.com/2009/04/python.html">こちら</a>)</p>
<pre name="code" class="python">
% python
Python 2.6.5 (r265:79063, Apr 16 2010, 13:57:41)
[GCC 4.4.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import this
The Zen of Python, by Tim Peters
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
</pre>
<!--The story behind "import this" is kind of funny, and occurred totally
behind the scenes, so I thought it might be interesting to relate how it
happened. Maybe something to add to Guido's History of Python blog.-->
<p>"import this"の背景の話は楽しいものなので、私は、これが追加された経緯について紹介したら面白いだろうと考えた。おそらく、<a href="http://python-history.blogspot.com/">Guidoの"History of Python"というブログ</a>に何かストーリーを追加するような内容になるはずである。</p>
<!--Anyway, back in fall 2001, Foretec was organizing the International Python
Conference #10 (IPC 10, precursor to Pycon). Foretec was a conference
organizing company owned by CNRI, which earlier had employed Guido, Fred,
Jeremy and myself, and which by 2000 we had left to form Pythonlabs at
various friendly (and occasionally disfunctional) corporate homes. By
September 13, 2001 (yes, how weird!) we were working for our friends at
Zope Corporation (perhaps not yet rebranded from Digitial Creations), but
Foretec was still organizing the IPCs. They wanted to have a slogan for the
conference, which could be printed on a t-shirt, and wanted to gather
submissions from the Python community. Pythonlabs agreed to judge the
entries and select a winner. However, I think Guido's wife was due any day
and he didn't have much time or energy to go through the entries.-->
<p>2001年の秋に、<a href="http://en.wikipedia.org/wiki/Foretec_Seminars">Foretec</a>は<a href="http://www.python.org/workshops/2002-02/spam1folks.jpg">International Python Conference #10</a> (IPC 10, <a href="http://www.pycon.org/">PyCon</a>の先駆けとなるイベント)の開催準備をしていた。Foretecは<a href="http://www.cnri.reston.va.us/">CNRI</a>の子会社のイベント運営会社で、<a href="http://www.python.org/pythonlabs/">Pythonlabs</a>の設立のために退社する2000年まで、Guido, Fred,Jeremyと私を雇っていた。その会社は<a href="http://en.wikipedia.org/wiki/History_of_Python#BeOpen">動きが悪いこともあった</a>が、好意的な面も多数ある会社であった。その時には既に、私たちは友人たちと一緒に<a href="http://www.zope.com/">Zope Corporation</a>(おそらく当時はまだ<a href="http://en.wikipedia.org/wiki/Zope">Digital Creations</a>という名前)で働いていたが、ForetecはIPCの開催を継続していた。ForetecはカンファレンスのスローガンをTシャツにプリントしたいと考えており、Pythonコミュニティからスローガンの提案を集めようと考えていた。提案されたエントリーを審査して、勝者を決めるというタスクを行うことをPythonlabsは同意した。しかし、私の記憶では、当時奥さんの出産を控えていたGuidoには、エントリーを審査する時間とエネルギーがなかった。</p>
<!--We got something like 500 entries, almost all of them terrible. Tim's
exact words were "Jeez Louise, I can't look at these for more than 5
minutes w/o my brain turning to mush" and yet he still managed to do an
initial cut down to something like 130 entries. While we had agreed to
choose a winner, we procrastinated until the last minute and by then it was
obvious that Tim and I were the only ones crazy enough to still care. Tim
suggested that we trade the list back and forth between the two of us, each
cutting the list in half until there was just one left. Tim is much better
at math than me, and I had forgotten about Python's integer division so I
was left to choose from between the last two entries: "Bite off all you
like - Chewing is optional" (yes, I said most were terrible ;), and "import
this". At the last minute, Tim resurrected a fun one that we had both
noticed approvingly early on: "Let's we study about Python program".-->
<p>私たちは500ほどのエントリーを受けつけたが、ほとんどはひどいものであった。Timは「Louise、5分も見ていると、脳が溶け出しそうになるよ」というようなことを言っていたが、なんとか作業を継続して、130エントリーほどになるまでカットした。最後の勝者が決まる、最後の1分まで、私たちはただただ気が狂いそうだった。Timは私に、リストを交換する提案をしました。リストを半分にして、半分だけ交換しました。Timは私よりも遥かに数学が得意であり、Pythonの<a href="http://docs.python.org/reference/expressions.html#binary-arithmetic-operations">数値の割り算</a>のくせを忘れていたため、最後の2つのエントリーが抜けてしまった。それらが「好きなものはすべて食べられます。咀嚼するのはオプションです」(私には良いところがまったくないと思われた;)と、「import this」であった。Timは「Pythonのプログラムに関して学ぼう」というエントリーについて二人ともが良いと思っていた土壇場になって、このおもしろいものを復活させた。</p>
<!--While that last one had lots of appeal, I liked the irreverent, almost
sneering tone of "import this". I saw the potential for a great, Michael
Jackson-esque t-shirt.-->
<p>私はこの「import this」という偉そうなセンテンスを気に入った。また、このセンテンスを利用すれば<a href="http://www.studio8.net/wp-content/uploads/2009/06/michael-jackson-crotch.jpg">マイケル・ジャクソン風の</a>すばらしいTシャツが作れそうだという可能性を感じた。</p>
<!--As soon as we'd chosen "import this" I realized we just had to implement
it. Python 2.2 was about to be released and I proposed that we turn off
checkin notifications and sneak in a "this.py" module which when imported
just printed the Zen of Python. Tim or Guido suggested further that we
rot13 the contents of the module just for a little extra obfuscation, and
we told no one outside our little group. According to my intergoogles
spelunking, as soon as IPC 10 was concluded, we commemorated the event by
committing this.py to what was to become Python 2.2.1, thus adding to the
affront of new features in point releases. IIRC, it took a long time for
someone to find our little easter egg.-->
<p>"import this"を選択してすぐに、それをプログラムとして実装した方がいい、ということに気づいた。Python 2.2のリリースが間近だったため、私は、コードのチェックインを知らせる機能をオフにして"this.py"というthe Zen of Pythonを表示させるモジュールを忍び込ませてはどうか?という提案をした。TimかGuidoのどちらかが、内容を難読化するのに<a href="http://ja.wikipedia.org/wiki/ROT13">rot13</a>という暗号化をしてみたらどうか?と提案した。その仲間内以外の人には誰にも話しをしなかった。Googleを探索して調べたところ、IPC 10が終了してすぐに、私たちはPython 2.2.1としてthis.pyをコミットして、このイベントを祝していた。つまり、2.2.1には、本来リリースすべき<a href="http://docs.python.org/library/functions.html#bool">真面目な機能</a>に加えて、このジョークの機能が追加されていたのである。私の記憶が正しければ、ここで仕込んだ小さなイースターエッグが発見されるまでには、多少の時間を要した。</p>
<!--That was all back in the day when the Python community had a sense of
humor.-->
<p>これは、Pythonコミュニティに<a href="http://ivory.idyll.org/blog/feb-10/whats-with-the-goat.html">ユーモアがあった時代</a>を思い出させてくれるできごとである。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com1tag:blogger.com,1999:blog-6018259859220218948.post-17060518788681637542010-07-13T03:00:00.003+09:002010-07-13T03:09:35.033+09:00import thisとThe Zen of Python<p>原文:<a href="http://python-history.blogspot.com/2010/06/import-this-and-zen-of-python.html">http://python-history.blogspot.com/2010/06/import-this-and-zen-of-python.html</a><br/>
原文投稿者:Guido van Rossum</p>
<!--Barry Warsaw posted an interesting blog that tells an obscure part of Python history (the kind I like to keep alive): -->
<p>Barry Warsaw氏が、Pythonの歴史の中で、今まで明らかにされていなかった(記録に残したい)事実を紹介する面白いエントリーをブログに投稿している。</p>
<p><a href="http://www.wefearchange.org/2010/06/import-this-and-zen-of-python.html">http://www.wefearchange.org/2010/06/import-this-and-zen-of-python.html</a></p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-5609431634142952162010-07-08T05:57:00.004+09:002010-07-08T06:41:06.434+09:00新スタイルクラスの内部の話<p>原文:<a href="http://python-history.blogspot.com/2010/06/inside-story-on-new-style-classes.html">http://python-history.blogspot.com/2010/06/inside-story-on-new-style-classes.html</a><br/>
原文投稿者:Guido van Rossum</p>
<!--[Warning, this post is long and gets very technical.]-->
<p>[注意:この投稿はとても長くて技術的です]</p>
<!--On the surface, new-style classes appear very similar to the original class
implementation. However, new-style classes also introduced a number of new
concepts:-->
<p>表面上は、新スタイルクラスは、元々のクラスの実装と非常に似通って見えるが、新スタイルクラスでは次のような数々の新しいコンセプトが導入されている。</p>
<!--* low-level constructors named __new__()
* descriptors, a generalized way to customize attribute access
* static methods and class methods
* properties (computed attributes)
* decorators (introduced in Python 2.4)
* slots
* a new Method Resolution Order (MRO)-->
<ul>
<li><tt>__new__()</tt>という名前の低レベルのコンストラクタ</li>
<li>属性アクセスのカスタマイズを一般的にできるようにするデスクリプタ</li>
<li>静的メソッドとクラスメソッド</li>
<li>プロパティ(演算してから結果を返す属性)</li>
<li>デコレータ(Python 2.4から導入)</li>
<li>スロット</li>
<li>新しいメソッド解決順序(Method Resolution Order, MRO)</li>
</ul>
<!--In the next few sections, I will try to shine some light on these
concepts.-->
<p>このエントリーでは、これらのコンセプトについて光を当てていこうと思う。</p>
<!--Low-level constructors and __new__()-->
__new__()という名前の低レベルのコンストラクタ
<!--Traditionally, classes defined an __init__() method which defined how new
instances are initialized after their creation. However, in some cases, the
author of a class may want to customize how instances are created?for
example, if an object was being restored from a persistent database.
Old-style classes never really provided a hook for customizing the creation
of objects although there were library modules allowed certain kinds of
objects to be created in non-standard ways (e.g., the "new" module).-->
<p>クラスを定義するときには通常の場合には、インスタンスの生成後にどのように新しいインスタンスを初期化するのかを定義する、<tt>__init__()</tt>メソッドを実装していた。しかし、クラスの作者が、インスタンスの生成方法そのものもカスタマイズしたいというケースがいくつかある。例えば、オブジェクトを永続化されたデータベースから復元する場合などである。"<tt>new</tt>"モジュールなど、普通ではない方法で特定の種類のオブジェクトを作成するためのライブラリはいくつかあったが、旧スタイルクラスではオブジェクトの生成をフックしてカスタマイズする方法が提供されていなかった。</p>
<!--New-style classes introduced a new class method __new__() that lets the
class author customize how new class instances are created. By overriding
__new__() a class author can implement patterns like the Singleton Pattern,
return a previously created instance (e.g., from a free list), or to return
an instance of a different class (e.g., a subclass). However, the use of
__new__ has other important applications. For example, in the pickle
module, __new__ is used to create instances when unserializing objects. In
this case, instances are created, but the __init__ method is not invoked.-->
<p>新スタイルクラスでは、<tt>__new__()</tt>という新しいクラスメソッドが提供されたことで、クラスの作者が新しいクラスのインスタンスを生成する方法もカスタマイズできるようになった。<tt>__new__()</tt>メソッドをオーバーライドして、以前作成したインスタンスを返すことで、クラス作者はシングルトンパターンのようなパターンも実装することが可能である。また、他のクラスのインスタンスも返すことができる。しかし、<tt>__new__()</tt>の活用法には、これ以外にももっと重要なものがある。例えば、<tt>pickle</tt>モジュールでは、<tt>__new__</tt>はシリアライズされたオブジェクトを復元してインスタンスを作成するのに使用されている。このケースでは、インスタンスは生成されるが、<tt>__init__()</tt>メソッドは呼び出されないという実装になっている。</p>
<!--Another use of __new__ is to help with the subclassing of immutable types.
By the nature of their immutability, these kinds of objects can not be
initialized through a standard __init__() method. Instead, any kind of
special initialization must be performed as the object is created; for
instance, if the class wanted to modify the value being stored in the
immutable object, the __new__ method can do this by passing the modified
value to the base class __new__ method.-->
<p>他にも、変更不可(immutable)型のサブクラス化を行う際にも、<tt>__new__</tt>が役に立つ。変更不可能という特性上、標準的な<tt>__init__()</tt>メソッドでは、このようなオブジェクトを初期化することはできない。そのため、オブジェクトの作成時に何か特別な初期化処理を行う必要がある。もし、変更不可能なオブジェクトの中に格納される値を変更したい場合には、ベースクラスの<tt>__new__</tt>メソッドに変更後の値を渡すことによって、このような処理を行うのに利用できる。</p>
<!--Descriptors-->
<span style="font-weight: bold;font-size:130%;">デスクリプタ</span>
<!--Descriptors are a generalization of the concept of bound methods, which was
central to the implementation of classic classes. In classic classes, when
an instance attribute is not found in the instance dictionary, the search
continues with the class dictionary, then the dictionaries of its base
classes, and so on recursively. When the attribute is found in a class
dictionary (as opposed to in the instance dictionary), the interpreter
checks if the object found is a Python function object. If so, the returned
value is not the object found, but a wrapper object that acts as a currying
function. When the wrapper is called, it calls the original function object
after inserting the instance in front of the argument list.-->
<p>デスクリプタは、旧スタイルクラスの実装の中心となっている、束縛メソッドの概念を一般化したものである。旧式のクラスでは、インスタンス属性がインスタンス辞書の中から見つけられない場合には、クラス辞書を引き続き探索し、その後はベースクラスのクラス辞書を再帰的にたどっていくという振る舞いをする。もし属性がクラス辞書の中で見つかると、インスタンス辞書とは異なり、インタプリタが見つかったオブジェクトがPythonの関数オブジェクトであるかどうかがチェックされる。もし、そのオブジェクトが関数オブジェクトだった場合には、見つけたオブジェクトを返値にするのではなく、カリー化関数のように振る舞うラッパーオブジェクトを返す。ラッパーが呼ばれると、インスタンスを引数リストの先頭に挿入してから、オリジナルの関数が呼び出される。</p>
<!--For example, consider an instance x of a class C. Now, suppose that one
makes a method call x.f(0). This operation looks up the attribute named "f"
on x and calls it with an argument of 0. If "f" corresponds to a method
defined in the class, the attribute request returns a wrapper function that
behaves approximately like the function in this Python pseudocode:-->
<p>例えば、クラス<tt>C</tt>のインスタンス<tt>x</tt>があると想定しよう。今、このインスタンスに対して、<tt>x.f(0)</tt>という呼び出しが行われたとする。この操作を分解すると、まず、"<tt>f</tt>"という名前の属性をインスタンス<tt>x</tt>から探しだし、引数として<tt>0</tt>を渡して呼び出される。もし、"<tt>f</tt>"がクラスの中で定義されたメソッドと一致するのであれば、次の擬似コードの関数のような振る舞いをするラッパー関数を属性として返す:</p>
<pre name="code" class="python">
def bound_f(arg):
return f(x, arg)
</pre>
<!--When the wrapper is called with an argument of 0, it calls "f" with two
arguments: x and 0. This is the fundamental mechanism by which methods in
classes obtain their "self" argument.-->
<p>もしも引数の<tt>0</tt>とともにこのラッパーが呼ばれると、このラッパー関数は<tt>x</tt>と<tt>0</tt>という二つの引数をともなって"<tt>f</tt>"を呼び出す。これが、クラスのメソッドが"<tt>self</tt>"引数を取得する基本的なメカニズムである。</p>
<!--Another way to access the function object f (without wrapping it) is to ask
the class C for an attribute named “f”. This kind of search does not return
a wrapper but simply returns the function f. In other words, x.f(0) is
equivalent to C.f(x, 0). This is a pretty fundamental equivalence in
Python.-->
<p>(ラップされていない)関数オブジェクトfにアクセスする別の方法としては、クラス<tt>C</tt>の属性として"<tt>f</tt>"という名前の属性の問い合わせをするというものがある。このような検索を行うと、ラッパーのつかない、関数<tt>f</tt>を単純に返す。言い換えると、<tt>x.f(0)</tt>は、<tt>C.f(x, 0)</tt>と同じということである。Pythonの中では、これらの呼び出しは基本的に等価である。<p>
<!--For classic classes, if the attribute search finds any other kind of
object, no wrapper is created and the value found in the class dictionary
is returned unchanged. This makes it possible to use class attributes as
“default” values for instance variables. For example, in the above example,
if class C has an attribute named “a” whose value is 1, and there is no key
“a” in x’s instance dictionary, then x.a equals 1. Assignment to x.a will
create an key “a” in x’s instance dictionary whose value will shadow the
class attribute (by virtue of the attribute search order). Deleting x.a
will reveal the shadowed value (1) again.-->
<p>旧式のクラスでは、属性を調べて、他の種類のオブジェクトが見つかった場合には、ラッパーは生成されずに、クラス辞書の中から見つかったオブジェクトがそのまま返される。これにより、クラス属性をインスタンス変数の"デフォルト"値として利用することもできる。例えば、上記の例であれば、もしクラス<tt>C</tt>が"<tt>a</tt>"という属性名で数値の<tt>1</tt>を持っていて、<tt>x</tt>のインスタンス辞書に"<tt>a</tt>"というキーがなければ、<tt>x.a</tt>は<tt>1</tt>となる。<tt>x.a</tt>に割り当てると、<tt>x</tt>のインスタンス辞書に"<tt>a</tt>"というキーができ、属性辞書の探索順序の影響でクラス属性の値が隠蔽される。<tt>x.a</tt>を削除すると、隠されていた値(<tt>1</tt>)に再びアクセスできるようになる。</p>
<!--Unfortunately, some Python developers were discovering the limitation of
this scheme. One limitation was that it was prevented the creation of
“hybrid” classes that had some methods implemented in Python and others in
C, because only Python functions were being wrapped in such a way as to
provide the method with access to the instance, and this behavior was
hard-coded in the language. There was also no obvious way to define
different kinds of methods such as a static member functions familiar to
C++ and Java programmers.-->
<p>残念ながら、何人かのPython開発者により、この実装の限界が発見されてしまった。限界の一つ目が、いくつかのメソッドPythonで実装し、他のメソッドをCで実装するという"ハイブリッド"クラスを実装することができないというものである。これはPythonの関数だけが上記のような方法でインスタンスにアクセスするためのメソッドを提供していたのと、この振る舞いが言語にハードコードされていたのが原因である。また、C++やJavaプログラマーが親しんでいる、静的メンバー関数のような異なる種類のメソッドを定義する方法もなかった。</p>
<!--To address this issue, Python 2.2 introduced a straightforward
generalization of the above wrapping behavior. Instead of hard-coding the
behavior that Python function objects are wrapped and other objects aren’t,
the wrapping is now left up to the object found by the attribute search
(the function f in the above example). If the object found by an attribute
search happens to have a special method named __get__, it is considered to
be a "descriptor" object. The __get__ method is then called and whatever is
returned is used to produce the result of the attribute search. If the
object has no __get__ method, it is returned unchanged. To obtain the
original behavior (wrapping function objects) without special-casing
function objects in the instance attribute lookup code, function objects
now have a __get__ method that returns a wrapper as before. However, users
are free to define other classes with methods named __get__, and their
instances, when found in a class dictionary during an instance attribute
lookup, can also wrap themselves in any way they like.-->
<p>この問題に対処するために、Python 2.2からは、上記のラッピングの振る舞いを素直に一般化した仕組みが導入された。Pythonの関数オブジェクトのみをラップするというハードコーディングされた振る舞いの代わりに、属性検索で見つかったオブジェクト(上記の例だと関数f)ごとにラッピングするようになった。もしオブジェクトが見つかると、<tt>__get__</tt>と呼ばれる特殊なメソッド名を持つ、「デスクリプタ」と呼ばれるオブジェクトが返される。次に<tt>__get__</tt>メソッドが呼ばれ、属性検索の結果として、このメソッドの返値が使用される。もしオブジェクトが<tt>__get__</tt>メソッドを持っていない場合には、それがそのまま返される。インスタンス属性検索コード内に特別な処理を行う関数オブジェクトを作らずに、関数オブジェクトをラッピングして返すという今まで通りの振る舞いにするために、関数オブジェクトには、以前のコードと同じようなラッパーを返す、<tt>__get__</tt>メソッドが追加された。このデフォルトのラッパー以外にも、ユーザが自由に<tt>__get__</tt>というメソッドを持つ他のクラスを定義し、インスタンス属性検索中でクラス辞書の中から発見された場合に、好きなようにラッピングすることもできるようになった。</p>
<!--In addition to generalizing the concept of attribute lookup, it also made
sense to extend this idea for the operations of setting or deleting an
attribute. Thus, a similar scheme is used for assignment operations such as
x.a = 1 or del x.a. In these cases, if the attribute "a" is found in the
instance's class dictionary (not in the instance dictionary), the object
stored in the class dictionary is checked to see if it has a __set__ and
__delete__ special method respectively. (Remember that __del__ has a
completely different meaning already.) Thus, by redefining these methods, a
descriptor object can have complete control over what it means to get, set,
and delete an attribute. However, it's important emphasize that this
customization only applies when a descriptor instance appears in a class
dictionary?not the instance dictionary of an object.-->
<p>属性検索コンセプトを一般化するのに加え、属性の設定と削除の操作にも、このアイディアを拡大して適用した。<tt>x.a = 1</tt>や<tt>del x.a</tt>など、今までと同じような割り当て操作を使用することができる。このような操作が行われた時に、"<tt>a</tt>"という属性がインスタンス辞書ではなく、インスタンスのクラス辞書の中で発見された時に、クラス辞書に保持されたオブジェクトに<tt>__set__</tt>や<tt>__delete__</tt>という特別メソッドがないかどうかチェックされる。(<tt>__del__</tt>というメソッドはまったく別の意味で既に使用されている。そのため、これらのメソッドを再定義することによって、デスクリプタオブジェクト属性の取得、設定、削除の操作の時にどのような処理が行われるかを、完全に制御することができる。しかし、デスクリプタインスタンスが、インスタンス辞書ではなく、クラス辞書内に設定された時にだけ適用されるという点は、重要なので最後にもう一度強調しておきたい。</p>
<!--staticmethod, classmethod, and property-->
<span style="font-weight: bold;font-size:130%;">staticmethod, classmethod, property</span>
<!--Python 2.2 added three predefined classes: classmethod, staticmethod, and
property, that utilized the new descriptor machinery. classmethod and
staticmethod were simply wrappers for function objects, implementing
different __get__ methods to return different kinds of wrappers for calling
the underlying function. For instance, the staticmethod wrapper calls the
function without modifying the argument list at all. The classmethod
wrapper calls the function with the instance's class object set as the
first argument instead of the instance itself. Both can be called via an
instance or via the class and the arguments will be the same.-->
<p>Python 2.2からは、<tt>classmethod</tt>, <tt>staticmethod</tt>, <tt>property</tt>という、新しいデスクリプタのメカニズムに関連する、3つのクラスが追加された。<tt>classmethod</tt>と<tt>staticmethod</tt>は、関数オブジェクトに関するシンプルなラッパで、保持している関数オブジェクトの呼び出し方が通常とは異なるラッパーを返す、<tt>__get__</tt>メソッドが実装されている。例えば、<tt>staticmethod</tt>のラッパーは、引数リストに変更をいっさい加えずに関数を呼び出す。<tt>classmethod</tt>のラッパーは、インスタンスそのものではなく、インスタンスのクラスを引数の先頭に追加してから関数を呼び出す。呼び出されるのがインスタンス経由であっても、クラス経由であっても、それぞれの引数は一緒となる。</p>
<!--The property class is a wrapper that turned a pair of methods for getting
and setting a value into an "attribute." For example, if you have a class
like this,-->
<p>propertyクラスは、"属性"に対する値の設定と、"属性"からの読み込みに関する対となる2つのメソッドを持つようなラッパーを生成する。例えば次のようなクラスがあったとする。<p>
<pre name="code" class="python">
class C(object):
def set_x(self, value):
self.__x = value
def get_x(self):
return self.__x
</pre>
<!--a property wrapper could be used to make an attribute "x" that when
accessed, would implicitly call the get_x and set_x methods.-->
<p><tt>property</tt>ラッパーを使うと、属性"x"にアクセスされたときに、値の読み込みと設定に、ここで定義された<tt>get_x</tt>, <tt>set_x</tt>メソッドが暗黙的に呼び出されるようにすることができる。</p>
<!--When first introduced, there was no special syntax for using the
classmethod, staticmethod, and property descriptors. At the time, it was
deemed too controversial to simultaneously introduce a major new feature
along with new syntax (which always leads to a heated debate). Thus, to use
these features, you would define your class and methods normally, but add
extra statements that would "wrap" the methods. For example:-->
<p>最初に<tt>classmethod</tt>, <tt>staticmethod</tt>, <tt>property</tt>が導入されたときには、これらを簡単に扱える、特別な文法がなかった。そのときは、新しい文法(常に激しい議論が巻き起こる)と一緒に新しい機能を導入しようとすると、議論が収束しなくなって、導入できなくなると考えられたので、機能の追加だけが行われた。そのため、この機能を使用する場合には、通常通りクラスとメソッドを定義したあとに、メソッドをラップするための追加の文を追加する必要があった。<p>
<pre name="code" class="python">
class C:
def foo(cls, arg):
...
foo = classmethod(foo)
def bar(arg):
...
bar = staticmethod(bar)
</pre>
<!--For properties, a similar scheme was used:-->
<p>プロパティについても、同様の作法に従っていた。</p>
<pre name="code" class="python">
class C:
def set_x(self, value):
self.__x = value
def get_x(self):
return self.__x
x = property(get_x, set_x)
</pre>
<!--Decorators-->
<span style="font-weight: bold;font-size:130%;">デコレータ</span>
<!--A downside of this approach is that the reader of a class had to read all
the way till the end of a method declaration before finding out whether it
was a class or static method (or some user-defined variation). In Python
2.4, new syntax was finally introduced, allowing one to write the following
instead:-->
<p>デスクリプタのやり方の不都合な点は、メソッド定義の最後まで読まないと、そのメソッドが静的メソッドが、クラスメソッドか、あるいはその他のユーザ定義の属性を持つメソッドか特定できないという点である。Python 2.4からは、最後に新しい文法が導入され、次のように書くことができるようになった。</p>
<pre name="code" class="python">
class C:
@classmethod
def foo(cls, arg):
...
@staticmethod
def bar(arg):
...
</pre>
<!--The construct @expression, on a line by itself before a function
declaration, is called a decorator. (Not to be confused with descriptor,
which refers to a wrapper implementing __get__; see above.) The particular
choice of decorator syntax (derived from Java's annotations) was debated
endlessly before it was decided by “BDFL pronouncement”. (David Beazley
wrote a piece about the history of the term BDFL that I'll publish
separately.)-->
<p><tt>@式</tt> というのを、関数定義の前の行に書くことができるようになった。この構文を、デコレータと呼ぶ。<tt>__get__</tt>を実装したラッパーを作成するデスクリプタと混同しないようにして欲しい。デコレータ構文の文法(Javaのアノテーションから派生)に関しての議論は、「BDFL宣告」によって文法が決定されるまで、延々と続いた。(David BeazleyはBDFLと言う用語の歴史に関しては、私が書いたものとは別々に書いている)。</p>
<!--The decorator feature has become one of the more successful language
features, and the use of custom decorators has exceeded my widest
expectations. Especially web frameworks have found lots of uses for them.
Based on this success, in Python 2.6, the decorator syntax was extended
from function definitions to include class definitions.-->
<p>デコレータ機能は、言語の機能の中で、もっとも成功したものとなった。「うまくいけばここまで広がるだろう」と予想していた範囲いっぱいまで、幅広くカスタムデコレータが使用された。特にウェブフレームワークはこの文法の使用方法について、さまざまな発見をして応用された。この成功を受けて、Python 2.6からは、この文法は関数定義だけではなく、クラス定義でも使用できるように拡張された。</p>
<!--Slots-->
<span style="font-weight: bold;font-size:130%;">スロット</span>
<!--Another enhancement made possible with descriptors was the introduction of
the __slots__ attribute on classes. For example, a class could be defined
like this:-->
<p>デスクリプタの導入によって可能になった別の拡張機能としては、クラスの<tt>__slots__</tt>属性がある。例えば、次のようにクラス宣言が行える</p>
<pre name="code" class="python">
class C:
__slots__ = ['x','y']
...
</pre>
<!--The presence of __slots__ does several things. First, it restricts the
valid set of attribute names on an object to exactly those names listed.
Second, since the attributes are now fixed, it is no longer necessary to
store attributes in an instance dictionary, so the __dict__ attribute is
removed (unless a base class already has it; it can also be added back by a
subclass that doesn't use __slots__). Instead, the attributes can be stored
in predetermined locations within an array. Thus, every slot attribute is
actually a descriptor object that knows how to set/get each attribute using
an array index. Underneath the covers, the implementation of this feature
is done entirely in C and is highly efficient.-->
<p>スロットが定義されると、いくつかのことが行われる。まず最初に、リストに定義されたのと同じ名前の属性しか、オブジェクトに定義できないように制限される。次に、属性が固定されると、それ以上はインスタンス辞書に属性を保持する必要がなくなるため、<tt>__dict__</tt>属性が削除される。ただし、ベースクラスにはそれがあり、<tt>__slots__</tt>を利用しないサブクラスで利用される。<tt>__dict__</tt>の代わりに、配列を使用して、予約された場所に属性が保存される。そのため、すべてのスロットの属性は、それぞれの属性が格納される配列のインデックスを知っている、デスクリプタのオブジェクトが割り当てられる。この機能の実装は、完全にC言語で構築されているため、とても効率が良い。</p>
<!--Some people mistakenly assume that the intended purpose of __slots__ is to
increase code safety (by restricting the attribute names). In reality, my
ultimate goal was performance. Not only was __slots__ an interesting
application of descriptors, I feared that all of the changes in the class
system were going to have a negative impact on performance. In particular,
in order to make data descriptors work properly, any manipulation of an
object's attributes first involved a check of the class dictionary to see
if that attribute was, in fact, a data descriptor. If so, the descriptor
was used to handle the attribute access instead of manually manipulating
the instance dictionary as is normally the case. However, this extra check
also meant that an extra lookup would be performed prior to inspecting the
dictionary of each instance. Thus the use of __slots__ was a way to
optimize the lookup of data attributes?a fallback, if you will, in case
people were disappointed with the performance impact of the new class
system. This turned out unnecessary, but by that time it was of course too
late to remove __slots__. Of course, used properly, slots really can
increase performance, especially by reducing memory footprint when many
small objects are created.-->
<p>中には、<tt>__slots__</tt>を導入した目的が、属性名を制限することによるコードの安全性の向上であると誤解している人もいる。実際には、私の究極の目標はパフォーマンスであった。導入の動機としては、<tt>__slots__</tt>はデスクリプタの面白い応用例であったから、というのもあったが、これらの新スタイルクラスに導入された変更は、パフォーマンスに対して深刻な影響を与えるのを恐れていたからである。特に、データデスクリプタを適切に動作させるには、オブジェクトの属性に対するあらゆる操作をする前に、データデスクリプタの場合には、まずその属性があるかどうか、クラス辞書を先に見に行く必要がある。その場合には、手動でインスタンス辞書を操作する代わりに、デスクリプタが使用されて属性アクセスが行われる。しかし、このようなチェックを追加する場合には、インスタンス辞書にアクセスする前に、追加の検索が実行されるということを意味している。スロットを利用することでパフォーマンスを向上させることができるため、万が一、新スタイルクラスを導入して、そのようにパフォーマンスの劣化で失望した場合に利用することができる。後になって(パフォーマンスの劣化が思ったよりも少なくて)、不必要であることが分かったが、その時にはもう削除するには遅かった。もちろん、適切に使用すれば、スロットはパフォーマンスを実際に増加させられる。特に、小さいにオブジェクトが大量に作成される場面では、メモリの使用量の削減によって、大きくパフォーマンスは向上する。</p>
<!--I'll leave the history of Python's Method Resolution Order (MRO) to the
next post.-->
<p>次の投稿では、Pythonのメソッド解決順序(MRO)の歴史に触れてみたいと思う。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-4125109535750301762010-06-26T19:55:00.004+09:002010-06-26T22:54:57.789+09:00新スタイルクラス<p>原文:<a href="http://python-history.blogspot.com/2010/06/new-style-classes.html">http://python-history.blogspot.com/2010/06/new-style-classes.html</a><br/>
原文投稿者:Guido van Rossum</p>
<!--Earlier, I described how the addition of classes to Python was essentially an afterthought. The implementation chosen was definitely an example of Python's "cut corners" philosophy. However, as Python evolved, various problems with the class implementation became a popular topic of griping from expert Python users.-->
<p>以前、Pythonへのクラスの追加は、本質的には後付であったという説明を行った。実装の選択は、Pythonの「手抜きをする」という哲学に従って行われた。しかし、Pythonが進歩するに従い、エキスパートのPythonユーザは、クラスの実装の問題について頻繁に不満を述べるようになってきた。</p>
<!--One problem with the class implementation was that there was no way to subclass built-in types. For example, lists, dictionaries, strings, and other objects were somehow "special" and could not be specialized via subclassing. This limitation seemed rather odd for a language that claimed to be "object oriented."-->
<p>クラスの実装の1つの問題は、組み込み型のサブクラス化を行う方法がなかったということである。例えば、リスト、辞書、文字列やその他のオブジェクトは何か「特別」なもので、サブクラス化して、一部を特殊化することができなかった。この制限は、「オブジェクト指向である」と主張していた言語にしては、奇妙に見えてしまっていた。</p>
<!--Another problem was that whole type system just seemed to be "wrong" with user defined classes. For example, if you created two objects a and b, statements such as type(a) == type(b) would evaluate as True even if a and b were instances of completely unrelated classes. Needless to say, developers who were familiar with languages such as C++ and Java found this be rather odd since in those languages, classes were tightly integrated with the underlying type system.-->
<p>他の問題は、型システムが全般的に、ユーザ定義クラスに関しては「間違っている」ようにしか見えなかったことである。例えば、まったく別の関係ないクラスのユーザ定義の2つのオブジェクトの<tt>a</tt>、<tt>b</tt>があったとすると、<tt>type(a) == type(b)</tt>を評価すると、真になってしまうのである。言うまでもなく、C++やJavaなどの、クラスが言語の型システムと密接に結びついているような他の言語に明るい開発者から見ると、かなりおかしく見えた。</p>
<!--In Python 2.2, I finally took the time to reimplement classes and "do it right." This change was, by far, the most ambitious rewrite of a major Python subsystem to date and one could certainly accuse me of a certain amount of "second-system syndrome" in this effort. Not only did I address the immediate problem of allowing built-in types to be subclassed, I also added support for true metaclasses, attempted to fix the naïve method resolution order for multiple inheritance, and added a variety of other features. A major influence on this work was the book "Putting Metaclasses to Work" by Ira Forman and Scott Danforth, which provided me with a specific notion of what a metaclass is, different from a similar concept in Smalltalk.-->
<p>Python2.2では、しっかりと時間をとって「正しく動作する」ようにクラスの再実装を行った。この変更は、Pythonのサブシステムをもっとも大々的に書き直したものとなったため、人々からは、この努力に対して「<a href="http://ja.wikipedia.org/wiki/%E4%BA%BA%E6%9C%88%E3%81%AE%E7%A5%9E%E8%A9%B1#.E3.82.BB.E3.82.AB.E3.83.B3.E3.83.89.E3.82.B7.E3.82.B9.E3.83.86.E3.83.A0.E7.97.87.E5.80.99.E7.BE.A4">セカンドシステム症候群</a>である」という非難を受ける可能性もあった。この変更では、組み込み型の継承ができないという問題を手っ取り早く修正するだけではなく、真のメタクラスのサポートの追加、多重継承時のメソッド解決順序という難しい問題の修正、その他の多くの機能の追加を行った。この仕事においては、"Putting Metaclasses to Work"という、Ira FormanとScott Danforthが書いた本の影響を強く受けている。この本は、Smalltalkとも違う、メタクラスが何かという示唆を私に提供してくれた。</p>
<!--An interesting aspect of the class rewrite was that new-style classes were introduced as a new language feature, not as a strict replacement for old-style classes. In fact, for backwards compatibility, the old class implementation remains the default class creation protocol in Python 2. To create a new-style class, you simply have to subclass an existing new-style class such as object (which is the root for the new-style class hierarchy). For example:-->
<p>クラスの書き直しに関しての面白い点は、旧スタイルクラスと置き換えて導入したのではなく、新しい言語機能として新スタイルクラスを導入したということである。後方互換性のために、Python 2のクラス作成プロトコルのデフォルトとして、旧スタイルクラスの実装はそのまま残された。新スタイルクラスを作成するためには、objectクラス(新スタイルクラス階層のルート)などの、既存の新スタイルクラスをただ継承するだけで行うことができる。</p>
<!--class A(object):
statements
...
<-->
<pre name="code" class="python">
class A(object):
実装
...
</pre>
<!--The change to new-style classes has been a major success. The new metaclasses have become popular amongst framework writers and explaining classes has actually become easier since there were fewer exceptions. The fact that backwards compatibility was maintained meant that old code has continued to work as new-style classes have evolved. Finally, although the old-style classes will eventually be removed from the languages, users are getting used to writing "class MyClass(object)" to declare a class, which isn't so bad.-->
<p>新スタイルクラスへの変更は大成功であった。新しく導入されたメタクラスは、フレームワーク作成者の中で人気の機能となったし、例外事項が減り、クラスを説明するのが簡単になった。実際、後方互換性は残されているため、新スタイルクラスの導入が行われても、古いコードは同じように動作させ続けることができた。最終的に、旧スタイルは言語から削除されることになると思うが、Pythonユーザは"<tt>class MyClass(object)</tt>"という、それほど悪くない書き方に、慣れてきている。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-81186623316276546712009-05-01T17:28:00.002+09:002009-05-01T17:39:12.895+09:00メタクラスとクラス拡張(通称:殺人ジョーク)<p>原文:<a href="http://python-history.blogspot.com/2009/04/metaclasses-and-extension-classes-aka.html">http://python-history.blogspot.com/2009/04/metaclasses-and-extension-classes-aka.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>Pythonの最初の実装では、クラス自身もファーストクラスオブジェクトであり、変数に入れたり、関数の属性に渡したり、他のオブジェクトと同じように扱うことができた。しかし、クラスオブジェクトを作成するプロセスは、石版に刻まれた手順がごとく、変更することはできなかった。具体的に説明すると、以下のようなクラス定義があったとする。</p>
<pre name="code" class="python">
class ClassName(BaseClass, ...):
...メソッド定義...
</pre>
<p>クラスの本体は、新しく作られるローカル辞書の中で実行される。クラス名、ベースクラスが格納されたタプル、そしてこのローカル辞書の3つが内部のクラス作成関数に渡される。この関数が最終的にクラスオブジェクトを作成する責任を持っている。これらの工程は隠れて見えなかったが、そもそもユーザが心配する必要のない、実装の詳細にあたる部分であった。</p>
<p>Don Beaudry氏はエキスパートユーザのために、隠れた可能性を指摘した最初のユーザであった。具体的には、もしクラスそのものもシンプルで特別なオブジェクトであるならば、通常とは違う動作をする、新しい種類のクラスを作ることはできないのか?というものであった。彼はインタプリタにわずかな修正を加え、C言語のコードの拡張モジュールを使って、新しい種類クラスを作れるようにして、それを提案した。この変更が初めて紹介されたのは1995年であった。これは長い間、"Don Beaudryフック"もしくは"Don Beaudryハック"と呼ばれた。名前があいまいだったのはジョークだと思われていたからである。その後、Jim Fulton氏がその修正を一般化し、ドキュメントは不十分ではあったが、言語の一部にした。これは、Python 2.2で新スタイルクラスが導入されて、メタクラスの本当のサポートが始まるまでは、拡張可能なメカニズムとして言語に残っていた。これについては後で触れる。</p>
<p>Don Beaudryフックの基本的な考え方は、クラス作成の最終段階の中でカスタムクラスオブジェクトを作成する、というものであった。例えば、作成されたクラスに対して、ユーザの提供した関数を追加する、といったことが考えられた。具体的には、クラス名、ベースクラス、ローカル辞書の3つの情報を、通常とは異なるクラス作成関数に渡すことができれば、その関数はクラスオブジェクトを作成するための情報を使用してできることは何でもできるのである。唯一私が懸念していたのは、既に確立しているクラスの文法には変更を加えたくない、というものだけであった。</p>
<p>これを行うためには、当時はC言語で新しい型オブジェクトを作成し、呼び出し可能なオブジェクトとしてフックを作成する必要があった。そして、その呼び出し可能な型のインスタンスはクラス文のベースクラスとして使用され、そのクラスが標準のクラスオブジェクトを作成する代わりに、魔法のようにその型オブジェクトを呼び出されるようにするのである。呼び出し可能な型オブジェクトを提供する拡張モジュールを使用することで、クラス作成の振る舞いはこのように変更することができた。</p>
<p>最近のPythonユーザからすると、このようなハックは奇妙に思えるだろう。しかし、当時は型オブジェクトは呼び出し可能ではなかったのである。例えば、int型は組み込みの型ではなく、intオブジェクトを返す組み込み関数であった。int型自身は簡単にはアクセスできなかったし、呼び出すこともできなかった。ユーザ定義クラスもちろん呼び出し可能であったが、元々CALL命令を使ってオブジェクトを作成するというのは特殊なケースであり、組み込みの型はどれも、これとはまったく違う実装になっていた。Don Beaudry氏は最終的に、私の頭に最初のメタクラス、後の新スタイルクラスに繋がるアイディアを植え付け、最終的には古いクラスに引導を渡す役割を果たすことになった。</p>
<p>元々は、Don Beaudry氏自身が作成した、MESSという名前のPython拡張だけが、この機能を利用していた。しかし、1996年の末には、Jim Fulton氏は広く一般的になったExtension ClassesというサードパーティのパッケージをDon Beaundryフックを利用して開発した。Extension ClassesパッケージはPython 2.2がメタクラスをオブジェクト機構の標準の一部として導入して以降は、メリットがなくなった。</p>
<p>Python 1.5では、Don Beaudryフックを利用するために、C言語の拡張を作成しなければならないという制限が取り除かれた。これに加えて、呼び出し可能なベースクラス型のチェック機構を組み込み、"__calss__"という名前の属性をチェックも追加し、もしこの属性が存在していれば、クラス作成コードがこれを呼び出すようになった。私はこの機能についてのエッセーを書いた。これは多くのPythonユーザーにメタクラスのアイディアを紹介する、最初の文章となった。その文章には、頭を爆発させるようなアイディアが多く詰まっていたため、「<a href="http://ja.wikipedia.org/wiki/%E6%AE%BA%E4%BA%BA%E3%82%B8%E3%83%A7%E3%83%BC%E3%82%AF">殺人ジョーク</a>」というニックネーム(<a href="http://ja.wikipedia.org/wiki/%E7%A9%BA%E9%A3%9B%E3%81%B6%E3%83%A2%E3%83%B3%E3%83%86%E3%82%A3%E3%83%BB%E3%83%91%E3%82%A4%E3%82%BD%E3%83%B3">モンティ・パイソン参照</a>)がすぐについた。</p>
<p>Don Beaundryフックのもっとも偉大な功績は、クラス作成関数のAPIである。これはPython 2.2に持ち越され、メタクラス機構として実装された。前に説明したように、クラス作成関数は3つの引数を伴って呼び出される。クラス名の入った文字列。そしてベースクラスの入ったタプル(これは空でも、一つだけでも良い)、名前空間の中身が含まれている辞書である。この辞書にはメソッド定義や、その他のクラスレベルのコードが書かれたインデントブロックの内容が含まれる。クラス作成関数の返り値は、クラス名と同じ名前の変数に格納される。</p>
<p>当初は、これはただクラスを作成するためだけの内部APIでしかなかった。Don Beaudryフックは同じ呼び出し規約を使用するようになり、公開APIとなった。このAPIの見落とせないポイントは、メソッド定義が含まれるブロックはクラス作成関数が呼び出される前に定義されるということである。メタクラスはこの部分に対しては影響を与えることはできないため、メソッド定義が実行される名前空間の初期コンテンツに作用することはできないのである。</p>
<p>Python3000ではこの部分も変更され、メタクラスは通常とは異なるマッピングオブジェクトを提供し、その中でクラス本体の実行を行わせることができるようになる。これをサポートするために、明示的にメタクラス定義する文法も変更される。この目的のために、ベースクラスのリストの中でキーワード引数の文法を使用できるようになる。</p>
<p>
<b>訳注:</b>メタクラスの文法は以下のように変更された
<pre name="code" class="python">
# Python 2.x
class C(object):
__metaclass__ = M
...
# Python 3.x
class C(metaclass = M):
...
</pre>
</p>
<p>次のエピソードでは、メタクラスの考えが、いかにして2.2の新スタイルクラスの導入につながったのか、また、3.0の中で最終的に古い形式のクラスがどのように終局を迎えたか、ということについて、詳しく書きたいと思う。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-27999536615311711002009-05-01T12:52:00.003+09:002009-05-01T13:02:40.862+09:00ヘビ来襲!<p>原文:<a href="http://python-history.blogspot.com/2009/04/and-snake-attacks.html">http://python-history.blogspot.com/2009/04/and-snake-attacks.html</a><br/>
原文投稿者:Greg Stein</p>
<p>1995年に私は初めてPythonと遭遇した。Pythonを"ヘビ"として言及することは禁止されている。Pythonは爬虫類の方ではなく、<a href="http://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%B3%E3%83%86%E3%82%A3%E3%83%BB%E3%83%91%E3%82%A4%E3%82%BD%E3%83%B3">モンティ・パイソン</a>にちなんで命名されたからである。 もし誰かがあなたを攻撃していたら、犯人は<a href="http://en.wikipedia.org/wiki/Knights_who_say_Ni">Knights who say Ni</a>かおそらく<a href="http://en.wikipedia.org/wiki/Rabbit_of_Caerbannog">Rabbit of Caerbannog</a>である。</p>
<p><b>訳注:</b>Knights who say Niは、モンティ・パイソンの2作目のコメディ映画である、<a href="http://ja.wikipedia.org/wiki/%E3%83%A2%E3%83%B3%E3%83%86%E3%82%A3%E3%83%BB%E3%83%91%E3%82%A4%E3%82%BD%E3%83%B3%E3%83%BB%E3%82%A2%E3%83%B3%E3%83%89%E3%83%BB%E3%83%9B%E3%83%BC%E3%83%AA%E3%83%BC%E3%83%BB%E3%82%B0%E3%83%AC%E3%82%A4%E3%83%AB">モンティ・パイソン・アンド・ホーリー・グレイル</a>に登場する、騎士のグループのこと。Rabbit of Caerbannogはその映画に登場する殺人ウサギ。</p>
<p>とにかく、1994には私はLPMUD(マルチユーザのRPG)の中でフィクション上の悪役と闘っていた。Webはかろうじて存在していたが、ブロードバンドという言葉は聞いたことがなく、バンド幅が少なくてすむゲームが一般的だった。</p>
<p>もう少し戻ろう。1979年。私が最初に触れたコンピュータはAppleⅡだった。当時のお気に入りのゲームの一つが<a href="http://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%89%E3%83%99%E3%83%B3%E3%83%81%E3%83%A3%E3%83%BC%E3%82%B2%E3%83%BC%E3%83%A0">Colossal Cave</a>であった。その後は、<a href="http://ja.wikipedia.org/wiki/Zork">Zork</a>をプレイすることを覚えた。私はインタラクティブなフィクションというコンセプトと、これらのストーリーをコンピュータが制御しているということに心を奪われた。これらのゲームに捕まえられて、コンピュータのある生活がそこから始まった。(そう、25年以上して、Don Woods氏に会うことができたときの私の喜びは想像できるでしょうか?)</p>
<p><b>訳注:</b>Don WoodsはColossal Caveの開発者</p>
<p>MUDをプレイするのはとても面白かったが、私はこれらのゲームの作成を手伝いたいと思うようになってきた。私は<a href="http://en.wikipedia.org/wiki/Lima_Mudlib">LPMUDのゲーム作家</a>でコーダーで設計者でもある<a href="http://viega.org/">John Viega</a>氏に会った。そのとき彼はヴァージニア大学のコンピュータグラフィックスラボでAliceと呼ばれるシステムに関する仕事をしていた。このシステムはコンピュータに詳しくない人向けのシステムで、アニメーションを作成したい人向けに学びやすい言語を必要としていた。彼らは明快さ、パワー、シンプルさからPythonを選択した。</p>
<p>John氏はPythonの熱烈なファンで、私にPythonを紹介して「これだけは覚えて下さい!」「いいよ、いいよ」という会話した。その言語は簡単だがパワフルで、苦労しなくても何でもできた。</p>
<p>それが1995年の2月。私はまだそこから戻ってきていない。</p>
<p>そのときはあまり思っていなかったが、その後の私の仕事と人生にとって、Pythonは重要な軸となった。Guido氏の作品に感謝したいと思います。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-83729355219873619892009-05-01T11:20:00.002+09:002009-05-01T11:26:10.780+09:00Pythonの"関数型"の機能の起源<p>原文:<a href="http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html">http://python-history.blogspot.com/2009/04/origins-of-pythons-functional-features.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>私はPythonが関数型言語から強く影響を受けたことがあるとは一度も考えたことはなかったが、そのように言ったり思ったりする人はいるようである。私がそれまでに慣れ親しんできた言語は、C言語やAlgol 68のような命令的な言語である。Pythonの関数はファーストクラスオブジェクトとして作成されているが、Pythonを関数型のプログラミング言語として見たことはない。しかし、以前から、リストと関数を使用して、もっと多くのことをしてみたいと思うユーザがいたことは確かである。</p>
<p>リストに対して行う一般的な操作としては、リストのそれぞれの要素に対して関数を適用し、新しい配列を作成するというものがある。サンプルコードを上げると以下のような操作になる。</p>
<pre name="code" class="python">
def square(x):
return x*x
vals = [1, 2, 3, 4]
newvals = []
for v in vals:
newvals.append(square(v))
</pre>
<p>LispやSchemeのような関数型言語では、このような操作は言語の組み込み関数として用意されている。そのため、最初のころは、これらの言語に慣れていたユーザは同等の機能をPythonに実装していた。</p>
<pre name="code" class="python">
def map(f, s):
result = []
for x in s:
result.append(f(x))
return result
def square(x):
return x*x
vals = [1, 2, 3, 4]
newvals = map(square,vals)
</pre>
<p>上記のコードの微妙な部分としては、リストの要素に対して適用したい処理を、完全に独立した関数として別に定義しなければならないということを好まない人も少なからずいる、ということである。Lispのような言語では、map関数を呼ぶ時に簡単に関数を定義することができる。例えば、Schemeでは、無名の関数を作成することができるため、lambdaを使用することで1行で配列に対して処理を行うことができる。</p>
<pre name="code" class="python">
(map (lambda (x) (* x x)) '(1 2 3 4))
</pre>
<p>Pythonは関数をファーストクラスオブジェクトとして作成するが、関数型言語と同じように無名関数を作成する機能は持っていなかった。</p>
<p>1993年の終わり頃になると、何人ものユーザが、無名関数を作成するためのさまざまなアイディアを投稿してきた。これと同時に、リストを操作する、map(), filter(), reduce()といった関数も一緒に提案があった。例えば、"Pythonプログラミング"の著者のMark Lutz氏はexecを使用して無名関数を作成するコードをいくつか投稿した。</p>
<pre name="code" class="python">
def genfunc(args, expr):
exec('def f(' + args + '): return ' + expr)
return eval('f')
# サンプルの使用方法
vals = [1, 2, 3, 4]
newvals = map(genfunc('x', 'x*x'), vals)
</pre>
<p>Tim Peters氏は以下のようにユーザが入力できるように、構文を多少簡単にするための解決策を補足として提案した。</p>
<pre name="code" class="python">
vals = [1, 2, 3, 4]
newvals = map(func('x: x*x'), vals)
</pre>
<p>上記の例から、関数型のような機能が要望されているのは明らかであった。しかし同時に、文字列として書かれた無名関数をexecの中で手動で処理するのは極めてトリッキーなやり方に見えた。そのようなこともあり、1994年の1月には、map(), filter(), reduce()の3つの関数が標準ライブラリに追加されることとなった。これに加えて、より直感的な文法で無名関数を式として作成するための、lambda演算子も導入された。lambda演算子の使い方は以下の通りである。</p>
<pre name="code" class="python">
vals = [1, 2, 3, 4]
newvals = map(lambda x:x*x, vals)
</pre>
<p>この機能追加は、初期のころに、ユーザの提供したコードによって行われたという意味で、Pythonのコミュニティにとっては意義深いものであった。しかし、残念なことに著者の名前を思い出せず、SVNのログにもこの記録がないのである。もしこの読者の中にこのコードの作者がいるのであれば、コメントを是非とも残して欲しい。</p>
<p>私は"lambda"という用語の使用については全面的に賛成ではなかったが、代替案もなかったために、Pythonに取り込まれることになった。その用語を選択したのは現在は無名の貢献者であるが、当時は<a href="http://www.python.org/dev/peps/pep-0001/">良く</a>も<a href="http://yellow.bikeshed.com/">悪く</a>も、現在と比較して、少ない議論でどんどん大きな変化を行わなければならない時期であった。</p>
<p>lambdaはただ、無名関数を定義するための文法的なツールを実現する、という意図だけで作成されたものである。しかし、この用語の選択によって、予期していなかったような問題がいくつも起きることになった。例えば、関数型言語に通じたユーザは、他の言語のlambdaの意味と完全に一致していることを期待してPythonのlambdaを使用した。しかしPythonの実装には高度な機能が大きく欠けているという違いがあったのである。例えば、lambdaにまつわる微妙な問題として、lambdaの式がスコープ内の周りの変数を参照できなかったというものである。以下のコードはmap関数の中のlambda関数で未定義の変数'a'を参照したというエラーが発生して処理が止まってしまうのである。</p>
<pre name="code" class="python">
def spam(s):
a = 4
r = map(lambda x: a*x, s)
</pre>
<p>直感的ではないが、この問題を回避する方法としては、デフォルト引数と隠されたパラメータとしてを通じてlambda式に値を渡すというものがある。</p>
<pre name="code" class="python">
def spam(s):
a = 4
r = map(lambda x, a=a: a*x, s)
</pre>
<p>この問題に対する「正しい」解決策としては、内部関数に対して、暗黙のうちにスコープ内のすべてのローカル変数の参照を渡すようにするというものがある。これは「クロージャ」として知られており、関数型言語の重要な機能の一つである。しかし、この機能はPython 2.1では"from future"でimprotしたときのみの先行機能機能として、Python 2.2では正式な機能として、ようやく取り入れられた。</p>
<p>lambdaや他の関数型の機能導入の動機になっていたmap, filter, reduce関数は、リスト内包表記と、ジェネレータ表現に取って代わられようとしている。実際、Python 3.0ではreduce関数は組み込み関数のリストから除外されることになっている。(lambda, map, filterはそのまま残るので苦情を言う必要はありません :-)</p>
<p><b>訳注:</b>reduceは組み込み関数からfunctoolsモジュールへ移動した。</p>
<p>私はPythonを関数型言語として見ていないが、クロージャの導入は価値があったと考えている。クロージャは他の多くのプログラミング機能の拡張の開発の役に立っているからである。例えば、新スタイルクラスや、デコレータなど、いくつかの新しい機能はクロージャを利用している。</p>
<p>最後になるが、Pythonは何年もかけて、いくつもの関数型言語機能を取り込んできたが、まだ「本当の」関数型プログラミング言語に見られる機能がいくつも欠けている。例えば、末尾再帰のような、最適化に関する部分にはまだ取り組んでいない。Pythonは極めて動的な性質があるため、HaskellやMLといった関数型言語で行われるような、コンパイル時の最適化を行うことはできないが、それはそれで<a href="http://hugunin.net/story_of_jython.html">かまわない</a>と考えている。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-61492198784893510582009-05-01T09:15:00.001+09:002009-05-01T09:21:34.175+09:00大規模(壮大)な名前の変更<p>原文:<a href="http://python-history.blogspot.com/2009/03/great-or-grand-renaming.html">http://python-history.blogspot.com/2009/03/great-or-grand-renaming.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>Pythonが最初に作られた当初は、私はいつも、時々サードパーティのライブラリとリンクする程度で、基本的にはスタンドアローンのプログラムとしてしか動かすことはないだろうと考えていた。そのため、ソースコードの中ではC言語のリンカのレベルのグローバル名を自由に定義していた。例えば、'object', 'getlistitem', 'INCREF'などといったグローバルな名前が使用されていた。Pythonの人気が高まるにつれて、組み込みバージョンのPythonについての問い合わせが増えてきた。組み込みというのは他のアプリケーションにライブラリとしてリンクして使用することである。EmacsがLispインタプリタを統合しているのとはそれほどの違いはない。</p>
<p>しかし、Pythonのプログラムが持つグローバル名と、組み込みを行うアプリケーションが定義しているグローバル名の名前の衝突が発生するために組み込み作業は複雑であった。特に、'object'という名前は人気があったために衝突が多かった。この問題に対処するために、すべてのPythonのグローバル名の先頭に"Py"もしくは"_Py"(内部的にしか使用しないが、技術的な理由からグローバルにしているもの)、"PY"(マクロ向け)を付けるという命名規約を導入することにした。</p>
<p>すでにサードパーティ製のモジュールがたくさん作られていたため、移行作業は後方互換性に考慮して行われることになった。コアな開発者であるほど以前の名前を覚えているだろうということを考え、2つのフェーズが用意された。フェーズ1ではリンカからは古い名前に見えるが、ソースコードでは新しい名前が使用できるように、大量のC言語のプリプロセッサマクロを使用して新しい名前を古い名前に変換するようにした。フェーズ2では、リンカからは新しい名前が見えるようにしたが、移行作業が遅れていた拡張モジュールのことを考慮し、今度は古い名前から新しい名前に変換するという、また別のマクロのセットを用意した。この2つフェーズの中では、古い名前と新しい名前が混在することができたので、プログラムが動作しなくなるということはなかった。</p>
<p><a href="http://svn.python.org/view/python/trunk/">Subversionのログ</a>から、これらの名前の変更の歴史を少し調べてみた。1995年の1月12日の<a href="http://svn.python.org/view?view=rev&revision=4583">r4583</a>から作業が開始されていることが分かった。この時に大規模な名前の変更が行われることが通知され、新しい名前をもつヘッダファイルが導入された。しかし、1996年の12月の時点ではまだ.cのソースファイルの名前の変更作業は継続していた。"Grand Renaming(壮大な名前の変更)"という内容で調べると、名前を変更しているだとか、名前を変更したという、この時期のチェックインコメントを頻繁に見つけることができる。後方互換性のためのマクロが最終的に削除されたのは2000年の5月で、Python 1.6のリリース作業の中で行われた。<a href="http://svn.python.org/view?view=rev&revision=15313">r15313のチェックインコメント</a>の中に、このイベントを祝うコメントが書かれている。</p>
<p>この壮大な作業の功績の多くは、Barry Warsaw氏とRoger Masse氏によるものである。彼らはスクリプトの助けも得ながら、ファイルの中の名前の変更という、地味な作業に参加して次々と進めてくれた。彼らは多くの標準ライブラリにユニットテストを追加するという、退屈な作業をコツコツと行うこともしてくれたのである。</p>
<p>Wikipediaでは、かつて行われた<a href="http://ja.wikipedia.org/wiki/%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%B9%E3%82%B0%E3%83%AB%E3%83%BC%E3%83%97">大規模な名前変更(Great Renaming)</a>の出来事ついて紹介されている。見たところ、USENETのグループの再編成のことのようである。私はおそらく、無意識のうちに「PythonのGreat Renaming」というイベントの名前を付けたということを思い出した。これ以降に行われた大規模な名前の変更として見つけられるのは、Pythonのドキュメント生成にも使用していたSphinxである。Zopeもかつて大規模な名前の変更を行ったことがある。ここであげた例と比較すると小さな話ではあるが、最近ではPy3kの議論の中で、PyStringをPyBytesに変更しようという議論も行われている。</p>
<p>大規模、もしくは壮大な名前の変更は、開発者のコミュニティにとっては、高い確率でケガを伴うイベントである。プログラマの頭の配線をつなぎ直す必要があるし、ドキュメントも書き直さなければならない。また、名前の変更前のパッチを名前の変更後に統合するという複雑な作業が発生することもある。これは特に、名前の変更が行われていないブランチが残っている場合多く発生する問題である。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-71034297541221213842009-05-01T07:06:00.002+09:002009-05-01T07:35:56.149+09:00モジュールの動的ロード<p>原文:<a href="http://python-history.blogspot.com/2009/03/dynamically-loaded-modules.html">http://python-history.blogspot.com/2009/03/dynamically-loaded-modules.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>Pythonの実装アーキテクチャは、開発の当初からC言語で書く拡張モジュールが作成しやすいような仕様になっている。しかし、初期の頃には動的なロードを行う技術がまだ明確になっていなかったため、このような拡張機能は、ビルド時にPythonと静的にリンクをする必要があった。これを行うために、C言語の拡張モジュールにはPythonと自分の拡張モジュールをビルドするMakefileを出力するシェルスクリプトが添付する必要があった。</p>
<p>この方法は小さなプロジェクトではうまく回すことができたが、Pythonコミュニティでは、予想を上回るペースで次々と新しい拡張モジュールが開発され始めていたため、コンパイルとロードを分離することができるような拡張モジュールへの期待が高まっていた。その後すぐにプラットフォーム固有の動的リンクAPIをラップしたインタフェースのコードが寄贈されて、".py"ファイルと同じようにimport文が外のディスクにある共有ライブラリを探しに行けるようになった。初めて動的ロードのことがCVSのログに登場したのは1992年の1月であり、1994年の末までにはほとんどすべての主要なプラットフォームがサポートされた。</p>
<p>動的なリンクのサポートはとても役に立つことが分かったが、それと同時にメンテナンスの悪夢に悩まされることになった。プラットフォームごとに異なるAPIを使用しており、何かしらの制約があるプラットフォームも存在した。1995年の1月には、動的リンクのサポートのコードは再構築され、すべての関連するコードは一つのソースファイルに集約された。しかし、結果として、プラットフォームごとの条件付きコンパイル指令(#ifdef)によって雑然とした大きなファイルが作られることになった。1999年の12月にはGreg Stein氏の協力を得て、プラットフォーム固有のコードはそれぞれのプラットフォームおよびプラットフォームのファミリーごとの固有のファイルに分割するという再構築を再度行った。</p>
<p>Pythonにおける動的ロード可能モジュールのサポートはこのように進展があったが、多くのユーザにとってはそのようなモジュールをビルドする手順というのは不可解なものとして残ってしまっていた。モジュールをビルドするユーザ数は大きく増えてきた。特に、SWIGのような拡張ビルドツールの導入もこれを後押しした。しかし、拡張モジュールを配布しようとするユーザは、プラットフォーム、コンパイラ、リンカのすべての考えられる組み合わせ上で、モジュールをコンパイルするという大きなハードルに直面した。最悪のケースのシナリオは、ユーザがそれぞれ、コンパイラとリンカに渡す正しい設定を書いたMakefileとコンフィグスクリプトを作成する必要があるというものである。あるいは、ユーザが自分の拡張モジュールの情報を、Python自身のMakefileに追加し、Pythonの部分再ビルドを行って、正しいオプションでモジュールのコンパイルを行う必要があった。しかし、この方法は、エンドユーザがPythonのソースファイルを手に入れなければならないのが問題である。</p>
<p>最終的には、distutilsと呼ばれるPython拡張のビルドツールが考案されて、どの環境でもPythonの拡張モジュールのビルドしてインストールできるようになった。Pythonのmakefileによって、必要なコンパイラとリンカのオプションはデータファイルに書き込まれるようになった。このファイルはdistutilsが拡張モジュールをビルドする際に参照される。distutilsのほとんどの部分はGreg Ward氏によって作成された。古いPythonのバージョンをサポートするためにdistutilsの最初のバージョンはPythonとは別に配布されたが、Python 1.6からは標準ライブラリのモジュールとしてPythonの配布物に統合された。</p>
<p>distutilsには他にも注目すべき点がある。ただC言語のソースコードから拡張モジュールをビルドするだけにとどまらず、様々なことができるようになっている。ピュアPythonのモジュールやパッケージのインストールにも使用することができるし、Windowsの実行可能なインストーラを作成したり、SWIGのようなサードパーティの作成したツールを実行することも可能である。しかし、多くの人は複雑で、メンテナンスをするのも苦労するようなdistutilsに悩むようになった。そのため、最近ではサードパーティによる代替策("eggs"の別名でも知られるez_install)も人気になりつつあるが、同様に、動かないという苦情が出たりして、開発コミュニティの分断を引き起こしてしまっている。この拡張モジュールのビルドを完全に一般化をするという課題は、本質的に難しい問題である。</p>
<p><b>※訳注:</b>distutilsのメンテナンスの苦労という話が出ているが、ez_installが備えている、パッケージ名を指定してウェブサイトからダウンロードしてインストールしたり、関連するモジュールを一緒にインストールしたり、適切なバイナリパッケージを自動選択したり、アップデートを行ったり、といったパッケージマネージャ的機能がなく、ソースコードからのクリーンインストールしかできないことを言っていると思われる。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-18242581759887460492009-04-30T23:00:00.002+09:002009-04-30T23:09:30.302+09:00整数の割り算の問題<p>原文:<a href="http://python-history.blogspot.com/2009/03/problem-with-integer-division.html">http://python-history.blogspot.com/2009/03/problem-with-integer-division.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>Pythonの整数の割り算は、初期の間違いが、とてつもなく大きな結果引き起こすという一つの例である。前に書いた記事で触れたが、Pythonは設計時に、ABCで使用されてきた数値の処理方法とは違う方法を採用している。例えば、ABCでは2つの整数の割り算を行うと、正確な有理数で表された結果が返された。しかし、Pythonでは整数の割り算を行うと、整数に丸められた結果が返される。</p>
<p>私の経験上、有理数を返すという方法は、ABCの設計者が期待したほどは成功しなかった。シンプルなビジネスアプリケーションのプログラム(税金の計算)を行ったときのに遭遇した事象が典型的な例である。期待していたよりもずっと処理速度が遅かったのである。デバッグをしたときに内部では何千桁もの精度の有理数の数値が使われていたということに気づいた。しかし、最終的な結果は、有効数字が2桁か3桁に丸められて出力されるのである。この問題は、不正確なゼロ(inexact zero)を追加し始めることで簡単に修正することができたが、直感的とは言えないため初心者にはデバッグするのが困難である。</p>
<p>そのため、Pythonでは、ABCとは異なる、私が慣れ親しんでいたC言語に沿った数値のモデルに頼ることにした。C言語では、整数と浮動小数点数の両方で、さまざまなサイズが存在する。そこで私はPythonの整数の表現にはC言語のlong(少なくとも32ビットの長さは保証される)を利用し、浮動小数点数の表現はC言語のdoubleを利用することにした。また、私が"long"と呼ぶ、任意精度の整数型も追加した。</p>
<p>数値に関する大きな間違いは、高級言語ではなく、C言語に近いルールを採用してしまったことにある。例えば、割り算を含む、標準の数値演算子の結果は、計算に使用したのと同じ型が常に返るようにした。私は最初は、これとはまた別の間違ったルールを使用していた。それは、数値の型を混ぜて使うのを禁止したことである。このルールは型の実装をお互いに独立させるのを目的としていた。そのため、最初のPythonでは、int型にfloat型を足すこともできなかったし、int型とlong型を足すのもできなかったのである。そのため、Pythonが一般向けにリリースされた直後に、Tim Peters氏から、このルールは本当に悪い考え方であるということを納得させられ、通常の型強制ルールに従って数値型を混ぜて計算するモードを導入することになった。例えば、int型とlong型が混ぜて使用された場合には、引数の型をint型からlong型に変換し、計算結果はlong型を返す。また、float型が使用された場合には、int型やlong型の引数はfloat型に変換し、結果はfloat型で返すようになったのである。</p>
<p>しかし、整数の割り算の結果が整数になるというダメージは残っていたのである。もしかしたら「なぜこのことがそんなに悪いことなのか?」と思う方もいるかもしれない。何も問題がないのに、ただ騒いでいるだけなのか?と。歴史的には、この仕様を変更しようとすると、昔から強く反対する人々が必ず現れてきた。彼らは、数値の割り算を学ぶことは、すべてのプログラマが「通過する儀式」であると信じているのである。そのような方もいるため、なぜこの設計がバグであるかと考えている理由を説明していこうと思う。</p>
<p>もし、例えば、月の満ち欠けの計算などである数値計算を行う関数を実装していたとしよう。通常なら、引数として浮動小数点数を指定したいと思うだろう。しかし、Pythonでは型宣言がないため、呼び出し側が整数の引数を渡して呼び出すことを妨げることはできない。C言語のような静的な型を持つ言語であれば、コンパイラが強制的に型変換をしてfloatにするが、Pythonではそのようなことはない。数値を混ぜるルールによって中間結果がfloat型に変換されるまでは整数型で計算されることになる。</p>
<p>割り算以外の演算子の場合は、整数は浮動小数点数と同じ振る舞いをする。例えば、1 + 1は2になるし、1.0 + 1.0は2.0になる。そのため、引数が整数か浮動小数点数かに関わらず、数値計算のアルゴリズムが問題なく動作するという誤解が簡単に生じてしまうのである。しかし、計算に割り算が含まれていて、入力される数値が両方とも整数になる場合には、暗黙のうちに結果の切り捨てが発生する。そのため、計算結果に大きな問題が入り込む可能性が本質的に含まれるのである。すべての引数を入力の時点で浮動小数点数に変換するという防衛的なコードを書くのも面倒な作業であるし、コードの可読性とメンテナンス性を下げることになる。かなり特殊なケースではあるが、それに加え、同じアルゴリズムに対して、複素数を入力して計算することを妨げることにもなってしまうのである。</p>
<p>繰り返すと、Pythonが、宣言された型への引数の型変換を自動的に行わないのが問題の原因である。例えば、文字列のような適切でない引数が渡されると、掛け算以外の演算は文字列と数値を混合して扱うことができないため、すぐに問題の発生が特定できる。しかし、浮動小数点数が期待されているアルゴリズムに整数が渡された場合には、正解に近いがエラーを含む結果を返すことになる。中途半端に正確なため、デバッグをしたり、問題に気づくのが難しいのである。最近、アナログ時計を描くプログラムで、切り捨てのために針の位置の計算がおかしくなるという問題が発生した。しかし、一日に何回かしか問題に気づくことはできなかった。</p>
<p>整数の割り算を修正するのは簡単なタスクではない。というのも、整数の割り算の結果が整数になるというのを期待して作成されたプログラムもあるからである。今までの割り算と同じ機能を提供する演算子(//)もPythonに追加された。それに加え、新しい整数の割り算の機能を追加する("from __future__ import division")というメカニズムも提供され、使用できるようになっている。振る舞いを変更し、プログラムの変換の手助けをするコマンドラインフラグの(-Qxx)が提供されている。さらに幸運なことに、この正しい振る舞いは、Python3000では標準的な動作となるのである。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-91157815465089218582009-04-30T18:26:00.002+09:002009-04-30T18:33:18.595+09:00なぜ、例外がクラス化されたのか?<p>原文:<a href="http://python-history.blogspot.com/2009/03/how-exceptions-came-to-be-classes.html">http://python-history.blogspot.com/2009/03/how-exceptions-came-to-be-classes.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>初期のころから、私はPythonでエラーを扱うために例外を使用したいと思っていたことを覚えている。しかし、例外を動作させるために重要なことは、異なる例外の種類を識別させるのにはどのような分類方法を利用すればいいのかというのを思いつくことである。現代的な言語は(もちろん最近のPythonも:-)、ユーザ定義クラスを使用して例外を定義する。しかし、初期のPythonはそうではなく、文字列によって例外を識別する方法が選ばれた。この選択は失敗ではあったが、この方法を選択した理由は2つあった。まず最初に、私は例外をModula-3で学んだが、この言語では例外というのは、重複のないトークンが使用されていたからである。2つめの理由としては、ユーザ定義クラスが導入される前に例外を導入したことである。</p>
<p>理屈の上では、私が例外のために組み込みのオブジェクトの新しい型を作るということも考えられたが、すべての組み込みオブジェクトの型はC言語上で努力してかなりの量のコーディングを行う必要があるので、私は既存の組み込み型を再利用する方を選択した。例外はエラーメッセージと結びつけられることがあるので、例外を表現するのに文字列を使用するのは自然なことであると思われた。</p>
<p>後から考えると失敗だったのだが、私は、異なる文字列オブジェクトが異なる例外を表現する、というやり方を選択してしまった。例え同じ内容の文字列(同じ文字の並びが含まれている文字列という意味)であっても、違うものとして認識されてしまうのである。このやり方を選択した理由としては、異なるモジュールで定義された例外は、例え同じ内容の文字列であっても、独立してそれぞれ違う例外であると区別できた方がいいだろう、と思ったからである。この考え方は、例外は常に名前(中身ではなくて変数名)で参照され、オブジェクトの同一性で判断されるだろう、との判断からである。値の一致性で見るためには文字列の中身の同一性をみる必要があるが、これを行うことはないと考えていたのである。</p>
<p>この方法はModula-3の例外からの影響を受けていた。Modula-3では、例外宣言があると、重複のない「例外トークン」が作られ、他の例外トークンと区別がつかなくなることはない。私は、ポインタを使って例外を比較するように最適化を行い、文字列の値の比較をなくして、実行時間を最適化しようという間違った誘惑にかられてしまった。これは珍しいケースである。私はいつも自分のコーディング時にしか最適化を行わないのだから。もっとも大きな理由は、異なるモジュールで定義された関係のない例外の名前が衝突してしまう、ということを心配したからである。このため、私は例外を使用するやり方を厳密に決める必要がある、と考えていた。まず例外をグローバルの定数としてモジュール内に定義をして、例外を上げたり、受け取ったりするときには、そのグローバル定数の名前を利用するというものである。これは、文字列リテラルが自動的に隔離するようになる、ずっと前のことである。</p>
<p><b>訳注:</b>文字列の隔離というのは、同じ内容の文字列はメモリを共有して同じIDを持つように最適化することである。</p>
<p>悲しいことに、読者の方々の想像通り、実際にはこの方法はうまくいかなかった。初期のPythonユーザによって、同じ内容の文字列が合った場合に、同じモジュール内ではバイトコードコンパイラが統合してしまうことが発見された。これは、同じ文字列の値を持つ文字列リテラルがいくつも現れると、共有オブジェクトを一つだけ作る、ということである。この不具合により、例外は文字列の名前でも、エラーメッセージを含む文字リテラルの中身でも、同じように捕まえられることが判明したのである。実際には、同じモジュールの中で定義されたコードでのみ動作し、異なるモジュールの例外エラーメッセージを使って例外をキャッチしようとしても、不思議な失敗の仕方をしてしまうのである。言うまでもなく、これは広範囲にわたって混乱を発生させることになってしまった。</p>
<p>1997年のPython 1.5において、私は言語にクラス例外を導入した。Python 2.5まではレガシーアプリケーションをサポートするという目的で、文字列例外も残されてはいたが、クラス例外が推奨されることとなった。そして、Python 2.6において、最終的に文字列例外は姿を消したのである。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-85142025086069969912009-04-30T15:56:00.001+09:002009-04-30T16:00:18.551+09:00どのようにして、すべてが実行可能文になったのか?<p>原文:<a href="http://python-history.blogspot.com/2009/03/how-everything-became-executable.html">http://python-history.blogspot.com/2009/03/how-everything-became-executable.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>新しくPythonユーザになった人の中には、関数やクラスの定義まで含めて言語のすべてが実行可能文であるということを知って驚く人がいる。これは、あらゆるコードがプログラムのどこにでも現れることがある、ということを意味している。書こうと思えば、例えば"if"文の中に関数の定義を書くことも可能である。</p>
<p>最初の頃のバージョンのPythonの文法ではこのようにはなっていなかった。文法要素には「宣言フレーバー」と言うものがあり、import文や関数宣言などに使用されていた。これはその効果を使用したいと思うモジュールやスクリプトのトップレベルにしか置くことはできなかった。しかし、クラスのサポートを追加したときに、この文法は制限が多すぎると考えるようになった。</p>
<p>私の頭の中ではおおまかに以下のように推論していった。一連の関数宣言のみを使ってクラス本体の定義をするよりも、通常の変数割り当てをクラスの中で行った方がシンプルで道理に合っているだろう。しかし、これを許すのであれば、なぜもう一歩進めて、任意のコードの実行を許さないのだろうか?もしくは、さらに進めて、例えば"if"文の中に関数宣言を置くというようなことを認めてもいいのではないか?これを許可すると、文法をシンプルにすることができると即座に閃いた。インデントされているか否かにかかわらず、現在ある使用している文法と同じルールを共有することも可能である。そして、これらの文法を実現するのには、通常のコンパイラと同じバイトコードジェネレータ機能が利用できることが分かった。</p>
<p>この推論によって文法はシンプルになり、ユーザはPythonのコードをどこにでも書けるようになった。しかし、この機能は特定のプログラミングのスタイルのために必要だったというわけではない。例えば、Pythonではスコープのネストはサポートされていないが、技術的には関数宣言をネストするようなことも可能であった。そのような機能を念頭にいれてきちんと設計された言語と比べると、未定義な操作や、壊れた操作を引き起こす可能性もある。時間をかけて、多くのこれらの「壊れた」機能は修正されてきた。例えば、Python2.1以降は、ネストされた関数定義もきちんと動作するようになった。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-33205278054468853492009-04-30T13:27:00.002+09:002009-04-30T13:34:31.287+09:00すべてをファーストクラスに<p>原文:<a href="http://python-history.blogspot.com/2009/02/first-class-everything.html">http://python-history.blogspot.com/2009/02/first-class-everything.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>Pythonにおける私の目標の一つが、すべてのオブジェクトを「ファーストクラス」にするというものであった。これは、プログラミング言語の中のすべてのオブジェクト(数値、文字列、関数、クラス、モジュール、メソッドなど)に対して、名前をつけて、同じように取り扱うことができるようになるということを意味している。オブジェクトを変数に格納したり、リストの中に並べたり、辞書に格納したり、引数として渡したり、といったことが可能になるのである。</p>
<p>これを実現するためのPythonの内部実装はとてもシンプルになっている。すべてのPythonのオブジェクトは共通のC言語の構造体を元にしており、インタプリタ内のあらゆる場所で使用されている。変数やリスト、関数などは、このデータ構造のバリエーションを利用している。数値のようなシンプルなオブジェクトを表現しようとしたり、クラスのような複雑なものを実現しようとしないかぎり、この手法で大きな問題は発生しない。</p>
<p>「すべてをファーストクラスに」という考えを持つことは概念としてはシンプルであるが、一つだけクラスにまつわる取り扱わなければならない微妙な問題が存在する。それは、メソッドをファーストクラスオブジェクトにするという問題である。</p>
<p>以下のようなシンプルなPythonのクラスがあったとする(先週のブログからコピーしてきた)。</p>
<pre name="code" class="python">
class A:
def __init__(self,x):
self.x = x
def spam(self,y):
print self.x, y
</pre>
<p>もしメソッドがファーストクラスオブジェクトであった場合は、Pythonの中の他のオブジェクトと同様に、他の変数に割り当てることが可能になるだろう。例えば、"s = A.spam"というようなPythonのコードを書くことが可能になる。この場合、変数"s"はこのクラスのメソッドを参照しているが、これは関数そのものである。しかし、メソッドは通常の関数とは完全に同じではない。特に、メソッドの最初の引数は、メソッドが定義されたクラスのインスタンスが必ず入るという想定になっている部分が異なる。</p>
<p>この問題を取り扱うために、「非拘束メソッド(unbound method)」というものを作成した。非拘束メソッドは、メソッドを実装している関数オブジェクトを包む薄いラッパーである。このラッパーは最初の引数がメソッドが定義されたクラスのインスタンスになるという制限を加える。もし誰かが非拘束メソッド"s"を関数のように呼び出そうとした場合には、クラス"A"のインスタンスが最初の引数として渡されなければならない。サンプルを示すと、"a = A(); s(a)" という感じになる。</p>
<p>関連する問題が、オブジェクトの特定のインスタンスに関連づけられたメソッドを参照するようなPythonのコードを書いたときに発生する。例えば、誰かが"a = A()"のようにインスタンスを作成し、その後"s = a.spam"と書いたとする。このとき、変数"s"クラスのメソッドを参照しているが、この参照はインスタンス"a"を通じて得られたものである。このような状況を扱うために、「束縛メソッド(bound method)」と呼ばれる、また別の呼び出し可能なオブジェクトを使用することになった。このオブジェクトもまた、メソッドの関数オブジェクトを包む薄いラッパーになっている。このラッパーは裏で、メソッドを取得するのに使用した元のインスタンスを保持している。この後のコードで"s()"と呼ぶと、暗黙のうちに最初の引数にインスタンス"a"をセットしてメソッドを呼び出す。</p>
<p>実際には、束縛メソッドも、非束縛メソッドも同じオブジェクトを内部で使用している。このオブジェクトは、インスタンスへの参照を保持する属性を一つ持つ。この属性がNoneにセットされていると非束縛メソッドになり、そうでない場合には束縛メソッドになるのである。</p>
<p>束縛メソッドと非束縛メソッドなどはそれほど重要な問題には見えないかもしれないが、これらはクラスの動作の裏側を支える重要な部分である。プログラムの中で"s.spam()"というコードが出てくると、この文は実際には2ステップに分けられて実行される。まずは"s.spam"のメソッドの検索が実行される。この検索の結果、束縛メソッドである呼び出し可能オブジェクトが返される。その次に関数呼び出し演算子である"()"がこのオブジェクトに適用され、ユーザの指定した引数も渡されてメソッドが実行されるのである。</p>
<hr/>
<p>(*)Python3000では、非束縛メソッドの考え方が削除され、"A.spam"という式は、通常の関数オブジェクトを返すようになった。結局、最初の引数をAのインスタンスの限定しても、問題の分析の役に立つことはあまりない、ということになったのである。逆に高度な使い方を使用とした場合に邪魔になることも多かったからである。この高度な使い方というのは「duck typing self」という適切な名前で呼ばれている。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-61913383979259277222009-04-30T10:41:00.002+09:002009-04-30T11:05:02.173+09:00ユーザ定義クラスのサポートの追加<p>原文:<a href="http://python-history.blogspot.com/2009/02/adding-support-for-user-defined-classes.html">http://python-history.blogspot.com/2009/02/adding-support-for-user-defined-classes.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>にわかには信じられない人もいると思うが、CWIで開発が行われていた最初の一年の間、Pythonはクラスをサポートしておらず、最初の公開リリースの前にオブジェクト指向をサポートするようになった。どのようにクラスが追加されたかという過去の経緯を理解してもらう手助けになると思うので、現在のPythonがどのようにクラスをサポートしているのか、という点から話を始めようと思う。</p>
<p>Pythonはオーソドックスなスタックベースのバイトコードインタプリタ、もしくは仮想マシンとしてC言語で実装されている。プリミティブな型も同様にC言語で実装されている。アーキテクチャとしては一貫して「オブジェクト」を使用しているが、C言語はこのオブジェクトを直接サポートする仕組みを持っていない。そのため、構造体と関数ポインタを使用してこれらの仕組みが実装されている。Pythonの仮想マシンでは、すべてのオブジェクトの型がなるべく実装すべき演算子と、絶対に実装すべき演算子が何十個か定義されている。例えば「属性の取得」、「足し算を行う」、「関数の呼び出し」などである。オブジェクトの型は静的に確保された構造体として表現される。この構造体には標準的な演算子に関する関数のポインタが一式格納されている。ほとんどの場合は、これらの関数は静的な関数への参照で初期化される。いくつかオプションの演算子があるが、この関数ポインタをNULLのままにしておくことで、これを実装しないでおくことが可能である。実装されていないオプションを使った演算を行ってしまうと、実行時にエラーを生成するか、場合によってはデフォルトで実装されている演算子が代わりに使用される。Pythonの型の構造体にはさまざまなデータフィールドを格納することができ、このクラス固有の追加のメソッドへの参照も格納することもできる。この場合は、文字列(メソッド名)と関数ポインタ(実装)の配列として構造体の中に格納される。Pythonではイントロスペクションを行えるが、これは、実行時には他の要素と同様に、型構造体そのものもオブジェクトとして使用することができるようになっていることで実現されているのである。</p>
<p>実装における重要な側面は、これらの機能の実装がすべて、C言語を中心に実装されているということである。実際、標準の演算子やメソッドはすべてC言語の関数で使って実装されている。もともと、バイトコードインタプリタはピュアPythonの関数と、C言語で作成されたメソッドや関数を呼び出す機能しかサポートしていないのである。私の記憶が正しければ、PythonでもC++のようなクラス定義を追加して、Pythonでオブジェクトを作成する機能を追加したほうがいい、とアドバイスをしてくれたのは、私の同僚だったSiebren van der Zee氏が最初であった。</p>
<p>ユーザ定義のオブジェクトを実装するにあたり、私はなるべくシンプルな設計をとった。「クラスオブジェクト」への参照ポインタと、「インスタンス辞書」と呼ばれる辞書が格納できる、新しい種類の組み込みオブジェクトを用意した。これを使用することで、ユーザ定義のオブジェクトを表現するという仕組みになった。クラスオブジェクトは同じクラスに属するすべてのインスタンスで共有される。インスタンス辞書はインスタンス変数を格納する。</p>
<p>この実装では、それぞれのオブジェクトごとのインスタンス変数はインスタンス辞書に格納され、同じクラスのすべてのインスタンスで共有する要素や、特にメソッドは、クラスオブジェクトに格納される。クラスオブジェクトの実装においても、できるだけシンプルな実装を選択した。クラスのメソッドは、メソッド名をキーとする辞書に格納された。私はこれをクラス辞書と呼んでいた。継承をサポートするためにクラスオブジェクトには、ベースクラスに関連するクラスオブジェクト群への参照を追加した。その当時、私はあまりクラスには詳しくなかったが、その当時のC++が多重継承をサポートしたことについては知っていた。私は、継承をサポートするからには、単純なバージョンの多重継承をサポートした方がいいと考えた。このようにして、すべてのクラスオブジェクトはひとつ以上のベースクラスを持つことができるようになった。</p>
</p>このPythonのクラスの実装では、オブジェクトの裏側で動作しているメカニズムはとてもシンプルになっている。インスタンス変数やクラス変数が変更されると、裏側にある辞書オブジェクトに変更が反映されるという仕組みになっている。例えば、インスタンス上にインスタンス変数に値を設定すると、そのオブジェクトが持っている、ローカルのインスタンス辞書が更新されるのである。同様に、オブジェクトのインスタンス変数の値を見にいくときは、変数がその中に定義されているかどうか、そのオブジェクトのインスタンス辞書をただチェックするだけである。もし変数がその辞書の中にないとすると、少しだけ面白いことが発生する。この場合は、インスタンス辞書の次にクラス辞書の中の探索が行われ、それでも見つからなければ、ベースクラスのクラス辞書が順番に探索されていく。</p>
<p>このようなクラスオブジェクトとベースクラスの中を属性探索していくプロセスは、メソッドの場所を探索するのとほぼ一緒である。少し前に説明したように、同じクラスに属すすべてのインスタンスが共有しているクラスオブジェクトがあり、その辞書の中にメソッドが格納されている。メソッドが必要なときには、当然それぞれのオブジェクトが持つインスタンス辞書の中は探索しないだろう。その代わりに、まずクラス辞書の中を調べ、その後はメソッドが見つかって止まるまで、順番にベースクラスを見ていく必要がある。それぞれのベースクラスでは、同じ再帰的なアルゴリズムが実装されている。これは深さ優先、左から右へのルールと呼ばれている。これがほとんどのPythonのバージョンで用いられているデフォルトのメソッド解決順序(MRO)である。もっと新しい現在のリリースではより洗練されたMROを採用しているが、これについてはこれについては別の機会に話をしたいと思う。</p>
<p>クラスを実装する際に私が目標の一つとしていたのは、シンプルさを維持する、ということである。そのため、Pythonはメソッドを定義する時には事前のエラーチェックや整合性のチェックは行うことはない。もし、あるクラスが、ベースクラスで定義されているメソッドをオーバーライドした場合、再定義されたメソッドの引数の数は同一であるか、もしくは、オリジナルのベースクラスのメソッドと同じ呼び方ができるか、などのチェックが行われることはない。上記のメソッド解決順序のアルゴリズムは、ユーザが指定した引数がどんなものであっても、最初に見つけたメソッドを返し、その引数を渡してメソッドを呼び出すだけである。</p>
<p>このような設計を行ったが、この仕様の想定外の使われ方をしている機能も他にいくつか存在する。例えば、クラス辞書は当初、メソッドを置く場所として想定していたが、メソッドと同じように他の種類のオブジェクトを格納してはいけないという理由もなかった。そのため、数値や文字列といったオブジェクトをクラス辞書の中に定義したとすると、これらはクラス変数と呼ばれるものになるのである。通常の変数はそれぞれのインスタンスごとにデータを格納するが、これとは異なり、クラス変数はそのクラスの全インスタンス間で共有される変数となるのである。</p>
<p>Pythonのクラスの実装はシンプルであるが、驚くほどの柔軟さを備えている。実際に、実行時に簡単に中の情報を調べることができるという「ファーストクラスオブジェクト」だけを作成するような実装にはなっていないが、クラスを動的に変更することも可能である。例えば、クラスオブジェクトが作成された後であっても、クラス辞書を更新するだけで、メソッドを追加したり、変更したりすることができる。(*)Pythonの動的な性質が意味するところは、クラスのすべてのインスタンス、クラスのすべてのインスタンスそのサブクラスという単位で、すぐにこれらの変更が引き起こされるのである。同様に、それぞれのオブジェクトもまた、動的に追加したり、変更したり、インスタンス変数を削除することができる。Pythonのオブジェクトの実装が完了した後に知ったのだが、Smalltalkでは属性の追加はオブジェクト作成時に定義する時にのみ限定されているため、Pythonの実装はSmalltalkよりも自由である。</p>
<span style="font-weight: bold;font-size:130%;">classシンタックスの作成</span>
<p>ユーザ定義のクラスやインスタンスの実行時の表現が設計できたので、次のタスクは、クラス定義の文法を設計することである。具体的に言うと、メソッド定義もこれに含まれる。私が関数のシンタックスとは異なるメソッド用のシンタックスを追加したくない、と考えていたことが設計上の主な制約であった。似ているが微妙に異なるようなケースを扱うために文法とバイトコードジェネレータをリファクタリングするというのは、とても大きな仕事のように感じていたからである。しかし、例えば文法を同じにすることに成功したとしても、その次にはインスタンス変数を取り扱う方法を考え出す必要がある。当初は、C++のような、暗黙のインスタンス変数をエミュレートできないかと期待した。例えば、C++では、以下のようなコードでクラスを定義する。</p>
<pre name="code" class="cpp">
class A {
public:
int x;
void spam(int y) {
printf("%d %d\n", x, y);
}
};
</pre>
<p>このクラスではインスタンス変数xが定義されている。メソッドの中では暗黙的に、該当するインスタンス変数を参照しに行くことになる。例えば、spam()メソッドの中では、変数xは、関数のパラメータとして定義されたわけでも、ローカル変数として定義されているわけでもないため、クラスはxという名前を持つインスタンス変数であると断定するのである。そこで初めてxへの参照が、インスタンス変数と結びつけられるのである。私は当初は同じようなやり方をPythonの中でも提供できれば、と期待していた。しかしすぐに、変数宣言がない言語においては、インスタンス変数とローカル変数をエレガントに識別する方法が存在しないということが分かった。</p>
<p>理論的にはインスタンス変数の値を取得するの難しくはない。Pythonは既に、ローカル、グローバル、組み込みと、宣言のない変数名から順番に探索する機能を備えているからである。これらはすべて、名前をキーにした辞書にマッピングされて実装されている。変数参照ごとに、結果が見つかるまで、これらの辞書を順番に探索する。例えば、ローカル変数pと、グローバル変数qを持つ関数を実行していたとする。例えば、"print p, q"という文を実行する場合は、pはローカルなので、検索順序の最初にある、ローカル変数を格納している辞書を探索しただけで見つかる。変数qは最初の辞書の中には見つからず、グローバル変数を格納している2番目の辞書の中で見つかることになる。</p>
<p>メソッドの実行時に、メソッド検索リストの先頭に現在のオブジェクトのインスタンス辞書を追加するのは簡単な作業である。インスタンス変数xと、ローカル変数yを使用した、オブジェクトのメソッドの中で、"print x, y"があれば、検索過程の1番目にあるインスタンス辞書から変数xを見つけることは可能である。変数yは2番目の辞書であるローカル変数辞書の中にある。</p>
<p>この戦略の問題は、これがインスタンス変数の設定をぼろぼろにしてしまうというところにある。Pythonの変数割り当てでは、これらの辞書の中の変数名まで見にいくことはせずに、検索順の最初の辞書内の要素(通常はローカル変数)に関して単純に変数を追加したり変更したりしている。この仕組みがあるので、変数を定義すると、デフォルトではローカルスコープ内に作成されることになる。Pythonには「グローバル宣言」というものがあるが、これは関数や変数ごとのこの基本の動作を上書きして、グローバルスコープに変数を作成するために必要となる。</p>
<p>割り当てに関するこの単純なやり方をそのままにして、インスタンス辞書を検索順序の最初の順序においてしまうと、メソッド内でローカル変数を割り当てるのが不可能になってしまうことになる。以下のようなメソッドがあったとする。</p>
<pre name="code" class="python">
def spam(y):
x = 1
y = 2
</pre>
<p>変数xとyの割り当ては、xに関してはインスタンス変数xの定義の上書きになり、ローカル変数のコピーとなるインスタンス変数yが作成されることになる。インスタンス変数とローカル変数の検索順序を交換したとすると、単に問題がひっくり返るだけである。結果としてインスタンス変数に割り当てることが不可能になるのである。</p>
<p>インスタンス変数がすでに存在している場合のインスタンス変数への割り当て方を変更すると、今度はローカル変数への操作がうまく行かなくなってしまい、結果として<a href="http://ja.wikipedia.org/wiki/%E3%83%96%E3%83%BC%E3%83%88%E3%82%B9%E3%83%88%E3%83%A9%E3%83%83%E3%83%97%E5%95%8F%E9%A1%8C">ブートストラップ問題</a>になってしまう。どのようにしてインスタンス変数を初期化時に作成すればいいのだろうか?可能な解決策の一つとして、グローバル変数と同様に、インスタンス変数についても明示的に宣言しなければならない、とすることもできるだろう。しかし、こうしてしまうと、すべての変数の宣言が必要となってしまうため、私はこれを選択したいとは思わなかった。加えて、グローバル変数であると示すためには仕様を追加する必要があったが、グローバル変数に限って言えば、使う場面はほとんど特殊なケースのみで、ほとんどのコードでは慎重に使われている、という事情もある。インスタンス変数のための特別な仕様が必要ということになると、このグローバル変数の状況とは異なり、クラス内のあらゆるところで使用されることが前提となる。もう一つとりうる解決策としては、文法的にインスタンス変数とローカル変数の区別をきちんと行うようにする、というものもある。例えば、Rubyが現在取っているアプローチのように、すべてのインスタンス変数の名前を、@のような特殊文字で始まるようにしてしまうというものである。あるいは、特殊な命名規則をつけるとか、大文字小文字のルールを決めるというのもあるだろう。しかし、私はこれらの選択肢はどれも魅力的には感じなかったし、今も感じていない。</p>
<p>最終的に、私はインスタンス変数への参照を曖昧なままにするというアイディアをあきらめることにした。C++のような言語はthis->fooと明示的にインスタンス変数fooへの参照を書くことが可能である。このようにして書くことで、同名のローカル変数fooと区別することができるのである。そうして、私はインスタンス変数への参照方法を、このような明示的なやり方に限定することにした。加えて、私は現在のオブジェクトを示す、"this"のような特殊なキーワードを作成する代わりに、"this"あるいはそれと同等なものを、メソッドの最初の引数の名前から取ることにした。こうして、インスタンス変数はこの引数の属性として参照できるようになった。</p>
<p>このように明示的な参照をするようにしたため、メソッドの定義のために特別な文法を作成する必要もなくなったし、変数の検索のための複雑な仕組みについて悩む必要もなくなった。実際には、プログラマは、単純に最初の引数として、インスタンスが入る引数をつけて関数を作成するだけである。Pythonでは、この変数の名前として、"self"を慣例的に使用している。サンプルコードは以下のようになる。</p>
<pre name="code" class="python">
def spam(self,y):
print self.x, y
</pre>
<p>この方法は、私がModula-3で見た何かと似ている。私は既にModula-3のimportと例外ハンドリングの文法を参考にさせてもらっている。Modula-3はクラスは持っていないが、関数ポインタをメンバーとして持っているレコード型を作成することが可能である。関数ポインタメンバーは近くに定義されている関数であるかのように初期化される。メンバーの呼び出しへのシンタックスシュガーも追加される。例えば、xをレコードの変数、mを関数fに初期化されているレコードの関数ポインタメンバーであったとすると、x.m(args)の呼び出しは、f(x, args)と同等になる。この仕様は、典型的なオブジェクトとメソッドの実装と同じであり、Python同様に、最初の引数の属性と、インスタンス変数を同一視することが可能になる。</p>
<p>Pythonのクラスの文法の残りの部分は、これまで説明した仕様に従って決定されたり、他の実装によって課せられた制約によって決定された。class文も、シンプルにするという私の願望を維持するため一連のメソッド定義からなると考えたが、この慣習とは異なる実装になった。最初の引数が"self"という名前にする必要があるが、関数の定義とメソッドの定義は瓜二つな実装とした。それに加えて、特殊な種類のクラスのメソッド(コンストラクタやデストラクタなど)については、新しい仕様を考え出す代わりに、これらの機能はユーザが単純に特殊な名前(__init__や、__del__など)でメソッドを実装することで扱えるようにした。C言語の、アンダースコアから始まる識別子の名前はコンパイラの予約語であり、例えばC言語のプリプロセッサで展開される__FILE__などのように特殊な意味を持っていることが多いが、Pythonの特殊なメソッドの名前の規則はそのC言語を元にしている。</p>
<p>この結果、私が考えていたクラス定義のコードは以下のようなものになった。</p>
<pre name="code" class="python">
class A:
def __init__(self,x):
self.x = x
def spam(self,y):
print self.x, y
</pre>
<p>何度も繰り返すが、私は、事前に作成したコードを、なるべく多く再利用したいと思っていた。Pythonにおける関数定義は、関数オブジェクトへの参照を、現在の名前空間内の中の変数にセットする実行文である。このときの変数名は関数名が利用される。そして、クラスの扱いについて違うアプローチが思い浮かんだが、単純に新しい名前空間の中で実行される一連の文としてクラスの本体を解釈するのが良いと考えた。この新しい名前空間は保存され、クラス辞書を初期化してクラスオブジェクトを作成するのに使用される。採用された実装方法は、まずクラスの本体を無名関数に入れ、この無名関数はクラスの本体の中のすべての文を実行し、ローカル変数の辞書を結果として返す。この辞書はクラスオブジェクトを作成するヘルパー関数に渡される。最後に、このクラスオブジェクトは現在のスコープの中の変数に格納される。この時、クラス名が変数名として使用される。無名関数として実行されるため、クラスの本体の宣言中に文法的に正しいPythonの実行文は何でも入れられるのであるが、これを知って驚くユーザは多い。この機能は、使いやすさを犠牲にしない範囲で文法をなるべくシンプルにしたいという私の希望を率直に拡張した結果生まれたものである。</p>
<p>最後に、クラスのインスタンス作成の文法について説明したいと思う。C++やJavaのような多くの言語は、新しいクラスのインスタンスを作成するのに、"new"といった特殊な演算子を使用する。C++のパーサの中ではクラス名はどちらかというと、特殊な状態として扱われるため、このようなことが可能になっている。Pythonの場合はクラスも単に変数に格納されたクラスオブジェクトでしかないため、特別扱いされることはない。Pythonのパーサは、関数呼び出しがあったとしても、どのような種類のオブジェクトかということに関しては無関心なので、私はすぐにクラスオブジェクトを呼び出し可能なものとして作成するのが良いと思った。既にある関数呼び出しという機能を利用することで、新しい文法が不要となり、最小限の手間で実現できるからである。。頭の中の時間を今日まで戻すと、最近はインスタンス生成のパターンとしてファクトリー関数というものが好んで頻繁に使用される。私がPythonに組み込んできた機能はまさに、クラスをそれぞれのファクトリー関数に転換するというものであった。</p>
<span style="font-weight: bold;font-size:130%;">特殊メソッド</span>
<p>クラスの実装に関連する最後のセクションとして、私が主な目標としている、クラス実装をシンプルにするということに関して簡単に触れたいと思う。ほとんどのオブジェクト指向言語には、クラスに対してのみ適用されるような、特殊な演算子とメソッドが存在する。例えば、C++ではコンストラクタとデストラクタ専用の特殊な文法が存在し、通常の関数やメソッドを定義するために使用される通常の文法と異なっている。</p>
<p>私はオブジェクトが特殊な演算子を扱うのに、特殊な文法は導入したくないと思っていた。そのため、「特殊メソッド」として、__init__や__del__のような名前を事前に設定して、特殊な演算子とこの名前をマッピングすることによって扱えるようにした。これらの名前を定義することによって、ユーザはオブジェクトの構築と破棄に関連するコードが実装できるようになったのである。</p>
<p>私はこのテクニックをユーザのクラスに適用することによって、Pythonの演算子を再定義できるようにした。前に触れたとおり、PythonではC言語を使い、組み込みオブジェクトの機能(例えば、「属性の追加」、「足し算を行う」、「関数の呼び出し」など)を実装するために関数ポインタのテーブルを用いている。これらの機能をユーザ定義クラスの中で定義するために、様々な関数ポインタと、__getattr__, __add__, __call__といった特殊なメソッド名のマッピングをおこなった。新しいPythonオブジェクトをC言語で実装するときには、これらの名前と関数ポインタのテーブルの間の関連を定義する必要があるのである。</p>
<hr/>
(*) 最終的に、新スタイルクラスはクラスの__dict__の変更を制御するためにこれが必要であった。現在も動的に変更することはできるが、クラスの__dict__を直接操作するのではなく、属性割り当てを使用すべきである。SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-63025483109277656592009-04-28T20:46:00.002+09:002009-04-28T21:16:00.841+09:00Pythonの動的型システム<p>原文:<a href="http://python-history.blogspot.com/2009/02/pythons-use-of-dynamic-typing.html">http://python-history.blogspot.com/2009/02/pythons-use-of-dynamic-typing.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>ABCとPythonが大きく異なるのは、型システムに対する基本的な姿勢である。<a href="http://homepages.cwi.nl/%7Esteven/abc/">ABC</a>は静的な型付けを採用している。ABCコンパイラは常にプログラムの中の型の使われ方を分析し、どのように使用されているのか分析を行う。もしうまく分析できないときは、そのプログラムは拒絶され、処理が実行されることはない。 当時の他の静的な型を持つ言語とは異なり、C言語のように明示的な型宣言をさせる代わりに、ABCは型推論を行っていた。ただし、<a href="http://www.haskell.org/">Haskell</a>とは似てなかった。それとは対照的に、Pythonでは動的な型システムを採用している。Pythonコンパイラは、型がどのようにプログラムの中で使用されるかという点には無関心である。型のチェックはすべて実行時に行われるのである。</p>
<p>これはABCから遠く離れた仕様のように見えるかもしれないが、読者の方々が思ったほどの違いはない。他の静的な型を持つ言語とは異なり、ABCは静的な型チェックだけに頼って、プログラムをクラッシュから守ろうとしているわけではないからだ(<-現在からすると歴史的なことなので過去形を使ったほうがよかったかも:-)。ランタイムライブラリは実行されるたびに、引数の型がどのように操作できるかというチェックをすべて行っていた。これはコンパイラと同じ型チェックアルゴリズムを使い、健全かどうかのチェックの一部として行われていたのである。初期の言語実装の中では、このチェックアルゴリズムの完全な実装は行われていなかった。ランタイムライブラリが明示的に実行時の型チェックを行い、わかりやすいエラーメッセージを出してくれたため、ライブラリ自体がデバッグを手助けしてくれたのである。この機能は実装チーム向けに整備された。そのため、引数を間違って指定したために、未チェックの何かの操作が行われて、インタプリタがどこかに行ってしまってコアダンプする、ということは起きなかったのである。</p>
<p>しかし、ABCが静的な型のチェックに加えて、実行時にも型のチェックを行っていた本当の理由は別にある。それはABCがインタラクティブな実行を許容していたからである。インタラクティブなセッションの中では、ユーザがABCの文や宣言を入力し、入力が完了したらその場で実行される。インタラクティブセッションでは、数値型として変数を作ったり、それを消したり、文字列型として再作成(言い方を変えると、別の変数を同じ名前で作成)したり、といったことが可能であった。一連の手続きの中で再作成した場合には、最初に数値型で変数を作成し、その次に同名の変数を文字列型として作成すると、静的な型エラーが検知されることが期待されるだろう。しかしインタラクティブセッションの中では、文を越えて型チェックを強制させられて、再作成が禁止されてしまうと都合が悪いことがある。もし間違って変数xを数値型で作ってしまうと、変数xを別の型で作成することができなくなってしまうからである。双方を考慮して妥協した結果、ABCはグローバル変数のチェックには動的な型チェックを使用するが、ローカル変数に対しては静的な型チェックを使用するというところに落ち着いた。Pythonではこれをさらにシンプルに実装して、ローカル変数に対しても動的な型チェックを行うようにしたのである。</p>
<p>そのため、Pythonの型チェックのアプローチと、ABCが実装したアプローチは、実際にはそれほど大きな差はないのである。Pythonはシンプルに、コンパイル時の型チェックを完全になくした。型に関するすべてのエラーは実行時に捕まえられるため、Pythonインタプリタが動作停止させられることはない。実行時だけのチェックであっても、最終的な動作の安全には悪い影響を与えることはないのである。これはPythonの「うまく手を抜く」という設計哲学にきちんと合っていると言えるだろう。</p>
<p>しかし、一度でも動的な型システムを使おうとすると、もう戻ることはできなくなってしまうだろう。ABCの組み込みの演算子は、演算の形式を見て型を推測できるように、慎重に設計されていた。例えば、ABCのコンパイラは、"x ^ y"という形の式から、コンパイラは変数xとyは文字列であり、演算結果も同様に文字列であるということを推測を行う。Pythonではもはやこのような推測を、一般化して実装することは不可能である。例えば、"x + y"という式は文字列の結合にも使用できるし、数値の足し算にも使用できる。また、Pythonでは、自分で定義した型に対して、自分でオーバーロードして演算子の動作を書き換えることもできるからである。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-32831457953822037212009-04-27T23:59:00.004+09:002009-04-29T22:40:25.737+09:00初期の言語設計と開発<p>原文:<a href="http://python-history.blogspot.com/2009/02/early-language-design-and-development.html">http://python-history.blogspot.com/2009/02/early-language-design-and-development.html</a><br/>
原文投稿者:Guido van Rossum</p>
<span style="font-weight: bold;font-size:130%;">ABCからPythonへ</span>
<p>Pythonの開発のスタート時から、もっとも大きい影響を与えた言語は、1980年代の初め頃にLambert Meetens氏とLeo Geurts氏などがCWIで言語設計を行った<a href="http://homepages.cwi.nl/%7Esteven/abc/">ABC</a>である。ABCはBASICの代替の教育用言語を目指していた言語である。そしてパーソナルコンピュータのための言語および環境になることを目指した。ABCの開発は、最初にプログラミングのタスクを分析する作業から始まり、何度か大きなユーザテストを含むイテレーションを実行しながら、言語の設計が行われた。私がABCグループで持った役割というのは、主にこの言語本体と、統合編集環境の実装である。</p>
<p>Pythonがインデントをブロックの区切りに使うようになったのは、ABCからの直接もらってきたアイディアであるが、元々はこの考え方はABCから生まれたものではない。これはすでにDonald Knuth氏によって推奨されるようになっていたし、プログラミングのスタイルとしてよく知られていた。また、<a href="http://en.wikipedia.org/wiki/Occam_programming_language">occam</a>というプログラミング言語が既にインデントを採用していた。しかし、ABCの設計者は、節とインデントされたブロックとを区別するのにコロンを使用することを思いついた。コロンがないバージョンでの初期のユーザテストにおいて、プログラミングの最初の一歩を教わっている初心者にとって、インデントの意味があまり明快には区別できていないということが分かったからである。コロンの追加により、コロンの前後で何がどうつながっているのかということに注意が向けられるようになり、かなり明確に理解されるようになったのである。</p>
<p>いくつか修正があるものの、Pythonの主なデータ型もABCから取り入れられた。ABCの配列はバッグか、もしくはマルチセットのどちらかであり、改良されたB-tree実装を使って常にソートされるようになっていた。ABCのテーブルも、キーによって常にソートされているような連想配列である。私はどちらのデータ型も、私が予想するような一般的な使用方法にはそぐわないと考えた。例えば、ファイルから読み込んだ行の配列を表現する場合などである。ABCでは行番号をキーとするようなテーブルを使用する必要があり、行の挿入と削除が極めて困難であった。そこで、私はリスト型を、挿入と削除の操作が簡単にできるような柔軟なデータ型に変更し、リスト内の項目の順序に関しては、ユーザがすべてコントロールできるようにした。ソートされた結果が必要な時があれば、そのときだけsortメソッドがそれをサポートするという仕組みにしたのである。</p>
<p>私は、ソート済みテーブルの実装も、ハッシュテーブルの実装に置き換えた。私がハッシュテーブルを選択した理由は、ABCのB-treeを使った実装よりも早く、簡単であると信じていたからである。後に、理論上でB-treeの方がスペースの消費量も、消費時間も、多くの操作領域で優れているということが分かったが、実際はB-treeアルゴリズムがあまりにも複雑なため、正しく実装するのが困難であると判断した。同じ理由から、小さいテーブルサイズのときのパフォーマンスも、部分最適化を行った。</p>
<p>ABCのタプル型(変更できない配列)はそのまま残した。Pythonの変数やりとりの際のパック/アンパックできるようにする、という操作はABCから直接もらったアイディアである。タプルが配列の内部表現として使われるようになると、私は配列のようなインデックスとスライスの操作をタプルに加えた。</p>
<p>配列のようなインタフェースをタプルに追加した結果、長さが0か1という境界条件のタプルをどのように扱えばよいかを決める必要が発生した。ABCから持ってきたルールのひとつに「すべてのデータ型は、画面に表示されるか文字列に変換するときには、言語のパーサーが正しく受け取れる表現で出力されるべきである」というものがある。そのため、これに従うためには、長さが0と1のタプルの場合には何か目印を付ける必要があるのである。しかし、だからといって、1要素のタプルと、カッコなしの数式表現の違いをなくしたくはなかった。最終的には、不恰好ではあるが、現実的なアプローチとして, 1要素でカンマが後ろについている場合には要素数1タプルになり、"()"の場合には要素数がゼロのタプルになる、という表現を採用した。Pythonの通常のカッコの表現は、この問題を除けばタプルの文法で必要とされるものに対して、すべてそのまま同じである。空のタプルが「何もない」と表現されるため、単純なタイプ間違いがあれば容易に発見できるはずである。</p>
<p><b>訳注:</b>ここで言っている「要素数が0か1のタプル」というのは、数式の中では 4 - (1 + 2) <b>⇒</b> 4 - (3) <b>⇒</b> 4 - 3と、項目数がひとつだけのカッコは処理の過程で外されることになるが、データ構造としての要素数1のタプルにおいて、a = (3) <b>⇒</b> a = 3とされてしまうと、a[0]とアクセスができなくなってしまい、困ってしまうのでカッコは外れて欲しくない、という事象のこと。最終的には長さが0, 1のタプルは()および(1,)と表現するようになった。</p>
<p>Pythonの文字列は、表現以外はABCの文字列と非常に似た動作をするようにした。どちらも、文字列というのは変更不可能な文字列である。表現上異なっているのは、Pythonは最初の要素を0番目として順番を指定するところである。このときはインデックスで要素を指定できるデータ型にはリスト、タプル、文字列の3種類の型があった。私はこれらのシーケンスの操作を共通のコンセプトで一般化しようと決めた。この一般化により、どのシーケンス型であっても同じように基本の操作することができるようになった。例えば、長さの取得(len(s)), インデックス(s[i]), スライス(s[i:j]), ループ(for i in s)などである。</p>
<p>数値は、ABCから大きく外れた設計を行ったもののひとつである。ABCでは実行時には2つのデータ型があった。任意の精度の有利数として正確な数値が格納できる型と、CPU上の浮動小数点数で表された近似された値と拡張された指数の組み合わせで表現された数値型の2つである。有理数は私の視界の外にあった。私の体験談になるが、ABCで自分の税金を計算しようとしたことがあった。このプログラムはとてもシンプルに見えたが、ちょっとしたシンプルな数値を計算するのにものすごい時間がかかったのである。調査の結果、ABCは数千桁の精度の数値を使って計算を行い、画面に出力するときにギルダーとセントに丸めて表示しているということが分かった。Pythonでは伝統的な、CPUの持っている数値型と浮動小数点数をそのまま使用するという、良く使用されるモデルを採用した。Pythonの中では、これらの型はそれぞれ、C言語のデータ型のlongとdoubleに単純にマッピングされている。</p>
<p><b>訳注:</b>ギルダーはGuidoの出身のオランダの通貨。セントは米ドルと同じく、100セント=1ギルダー。</p>
<p>正確で限界のない数値を使って計算を行うという使い方も重要であると感じたので、bignumデータ型を追加した。私はこれをlongと呼んでいた。私は既に数年にわたってABCのbignumを改良したいと思い続けていた。ABCのオリジナルの実装は私が最初にABCに貢献したもののひとつである。これは内部は10進数で表現されていた。このコードをPythonの中で使用するのは簡単であった。</p>
<p>Pythonにbignumを追加したが、重要なことは、すべての数値の計算にこれを使用したいと思っているわけではなかった点である。私が自分で書いたPythonプログラムと、CWIの同僚が書いたプログラムをプロファイルした結果、ほとんどのプログラムの実行時間のうち、数値の計算が全体に占める割合が大きいことが分かった。また、もっとも多く数値が使われる場面というのは、メモリの範囲内に収まるような小さい配列のインデックスである。そのため、私が想定したのは「厳密な数学」の計算を行うか、アメリカの国家予算をセント単位で計算するかというケース以外の、一般的に使われる場面のほとんどすべてはCPUの数値に納まる、というモデルである。</p>
<span style="font-weight: bold;font-size:130%;">数値にまつわる問題</span>
<p>数値の実装、特に整数に関しては、設計当時に、私がいくつもの大きな設計間違いをしてしまった領域のひとつである。しかし、Pythonの設計に関連する重要な教訓をいくつも学ぶことができた。</p>
<p><b>訳注:</b>ここでこれから述べる問題は現在では解決済みです。</p>
<p>Pythonが異なる二つの整数型を持っているので、プログラムの中でまずはこの二つを見分ける方法を考える必要があった。私が選択した解決策は、制限のない長い数値(long型)を扱いたい場合には、ユーザにきちんと宣言をしてもらう、というものであった。具体的には数値の後ろにLをつけて書く(例えば、1234L)という方法をとった。「ユーザには、興味のない実装の詳細を気にさせてはならない」というABCに影響された哲学があるが、この分野ではPythonはこれを破ることになってしまった。</p>
<p>残念ながら、これは数多くある数値の問題の中では、小さい問題のひとつでしかない。もっとひどい問題は、私が実装したint型とlong型では、いくつかのケースで微妙に異なる動作をしたことである。int型はコンピュータの数値型で表現されているため、計算結果がオーバーフローすると32bitの境界でクリップされてしまうのである。C言語のlong型でも、同じことは時々起こった。さらに、int型は通常は正も負も扱える(符号つき)ものとして処理されるが、ビット演算やビットのシフト操作、、8進数や16進数との間の相互変換時には、正だけの(符号なし)の整数として扱われた。long型は常に符号つきとして扱われた。そのため、いくつかの演算では、数値がint型かlong型かによって計算結果が変化してしまっていた。例えば、32ビット環境の場合、1<<31(1を左に31ビット分シフトする)の結果は、32ビットの数値の中で最大の負の値が返ってくる。そして、1<<32では0となる。しかし、1L<31(long型で表現された1を左に31ビット分シフトする)の結果は、2**31と同じ大きな数値になるのである。1L<<32は同様に2**32と同じ結果となった。</p>
<p>これらの問題のいくつかを解決するために、簡単な修正をほどこした。ユーザに内緒で数値をクリップしてしまう代わりに、ほとんどの数値演算子を書き換えて、結果が合わないときはOverflowError例外が上がるようにした。一部、ビット演算に関しては、ユーザはC言語とおなじ結果を期待すると思われたので、上記のチェックは入れなかった。もしこのチェックを入れていなければ、Pythonユーザは、C言語ユーザと同様に、符号つきの2**32という領域内でしかきちんと計算できないという認識に頼ったコードを書き始めていたことは疑いないだろう。そして、これらの問題の修正は、コミュニティにとってはより苦痛の大きい移行となっただろう。</p>
<p>オーバーフローのチェックは実装の詳細としては小さな問題に見えるかもしれないが、かなり困難を極めたデバッグの体験から、この機能はとても便利な機能であると実感していた。私が最初に実装したPythonプログラムのひとつに、Meertens数の計算という、シンプルな数値計算アルゴリズムを実装しようとしたものがあった。ABCのメインの作者のRichard Bird氏がCWIに勤めて25周年になった記念の、ちょっとした息抜きの数学の問題であった。最初のいくつかのMeertens数は小さいが、中間の結果は32ビットで扱えるよりも遥かに大きい数になるということを私は認識していなかった。私はこの事実を発見するまでは、長く苦しいデバッグの苦労を味わうことになった。この事実に気づいたときに、その場ですぐにすべての数値演算にオーバーフローチェックを入れて、C言語のlongで扱えない結果になるときはいつでも例外が上がるようにして、問題を特定することができた。オーバーフローのチェックにかかるオーバーヘッドのコストは、結果のための新しいオブジェクトの割り当てを実現するために既にかかっているコストを考慮すると、小さなものである。</p>
<p><b>訳注:</b><a href="http://ja.doukaku.org/">どう書く?org</a>の説明によると、Meertens数の定義は以下の通りである。
<br/>
<blockquote>
<p>正の整数 n を引数としてとり, 2^d1 * 3^d2 * 5^d3 ... * pk^dk を返す関数
がgoedel関数である。ただし,n を10進表現で k 桁の数としたときの各桁の数が数列 [d1,d2,d3,...,dk]
をなすとし,dk が 1 の位,d1 が 10^(k-1) の位。また,pk は k番目の素数。</p>
<ul>
<li>goedel 9 ⇒ 2^9 ⇒ 512</li>
<li>goedel 81 ⇒ 2^8 * 3^1 ⇒ 768</li>
<li>goedel 230 ⇒ 2^2 * 3^3 * 5^0 ⇒ 108</li>
</ul>
<p>このgoedel関数を適用すると自分自身になるような数,すなわち goedel (n) == n となるような正整数 n がMeertens数である。</p>
</blockquote>
</p>
<p>読者の方には、オーバーフローの例外を上げるというのも、最終的な解ではなかった、ということを謝らなければならない。当時の私は「T型の数値演算の結果は、同じT型になる」というC言語のルールにとらわれていたのである。このルールもまた、数値の意味を考える上で、私が大きな間違いをしてしまった原因である。数値の割り算の結果の切り捨てについてはまた別のブログの記事で説明をしたいと思う。後になって思うと、オーバーフローの時には例外を投げるのではなく、結果をlong型にして返すようにするべきであった。これは現在のPythonの実装のやり方である。しかし、このように移行するまでには長い期間がかかってしまった。</p>
<p>このような数に関する問題には苦労してきたが、ひとつだけ、とてもポジティブな考えをこの経験から生み出すことができた。それはPythonでは未定義な結果というのを根絶しよう、と意志を固めたことである。正しい計算結果が返せないときには、いつでも例外を上げるべきである。そのため、Pythonのプログラムは、見えないところで渡される未定義の値によって問題が引き起こされるということはないだろう。この考え方は、言語、つまり言語そのものと標準ライブラリの双方にとって、今日でも重要な原則となっている。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-8809695515967126552009-04-26T20:09:00.004+09:002009-04-26T21:01:24.354+09:001996年にMicrosoftが出荷したPythonコード<p>原文:<a href="http://python-history.blogspot.com/2009/01/microsoft-ships-python-code-in-1996.html">http://python-history.blogspot.com/2009/01/microsoft-ships-python-code-in-1996.html</a><br/>
原文投稿者:Greg Stein</p>
<p>私のPythonの歴史をここで共有することを受け入れてくれたGuido氏に感謝します。</p>
<p>自分のPythonとの出会いに関しては他の投稿に譲ろうと思うが、自分の仕事とPythonが関係することになったところから話を始めようと思う。私は数人のメンバーと一緒に、1991年にベンチャー企業を共同出資で設立した。私たちの業務は企業と消費者との間で行われる電子商取引を扱う大きなクライアント/サーバシステムであった。カスタムのTCPプロトコルを、古いX.25ネットワーク上で流したりしていた。私の出身はそのようなところである。</p>
<p>1995年には、我々が以前に行っていた予測とは大きく状況が変化し、多くの消費者がインターネット上に出てくるようになった。我々は、顧客(ベンダー)がインターネット上の消費者をターゲットとして使用できるシステムを準備する必要が出てきたのである。私は、どのようなアプローチをすればいいのかを調査するために、プロトタイピングツールとしてPythonを選択した。</p>
<p>最初の問題は、完全にブラウザベースのソリューションへの移行が必要となったことである。我々がそれまで開発してきたカスタムのクライアントソフトウェアはこれ以上生き残る術はなかった。我々は新しいショッピングの体験を消費者に提供する必要があり、サーバインフラはそれを支える必要があった。その当時はウェブブラウザとの通信というと、ApacheかNetscapeのHTTPサーバ上にCGIスクリプトを作成することを意味していた。CGIを使用すると、既存のバックエンドサーバに接続することができ、注文の処理、買い物かごの維持、商品情報の取得を行うことができた。これらのCGIスクリプトは素のHTMLを生成した。1995年にはAJAXはなかった。</p>
<p>このアプローチでは、リクエストごとに新しいCGIプロセスを起動するのに時間がかかるため、理想的な方法とは言えなかった。反応速度が極めて低かったのである。ちょうどそのころ、1995年の12月にワシントンDCで行われていたPythonワークショップに参加した。そのときに、Zopeでよく知られるDigital Creations社の人に、サーバプロセスの中に永続的にプロセスが走り続けるようになるというApacheとNetscapeのモジュールを紹介された。これらのモジュールはRPCシステムコール上のILU(多言語対応インタフェースシステム)を使い、バックエンドの長時間起動しているプロセスと通信を行うのである。このシステムを使用すると、CGIをフォークするオーバーヘッドがなくなり、ショッピングの体験が極めて快適なものに変わるのである。私はプロトタイプを実際のコードに変換していった。プロジェクトに取り組めば取り組むほど、どんどん良くなっていき、多くの人がこのプロジェクトに飛びついてくるようになった。Pythonのおかげで数ヶ月間、作業は<b>とても</b>早く進んだ。</p>
<p>1996年の1月に、Microsoft社が我々の会社を訪ねてきた。社内で電子商取引システムを構築しようと努力はしたものの、うまく道が見えないでいた。そのため、電子商取引に通じていて、機転の利く技術者を必要としていたのである。我々はこの分野では何年もの実績があった。春の間、交渉の間もソフトウェアの開発は続けた。そして、1996年の6月に買収は完了した。</p>
<p>Microsoft社にPythonコードの山と一緒に到着すると、まず行う必要があったことは、Windows NT上に電子商取引のソフトウェアを搭載する方法を理解することであった。Windowsの経験が豊富なチームに合流し、名前付きパイプを使ってバックエンドのサーバと通信するIISプラグインを構築した。このバックエンドサーバは、我々のPythonサーバコードが組み込まれたNTのサービスである。泥のようなスプリントが7月から始まり、我々はMicrosoft Merchant Server 1.0を1996年の10月に出荷することができた。</p>
<p>そう。もしシステムの中を見ることができたら、そこに隠れているのは・・・Pythonインタプリタと、いくつかの拡張DLL、そして.pycファイルの山である。Microsoft社はこの事実を宣伝することはなかったが、もし知っていたら見ることが可能だったのである。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-39887244111824393602009-04-26T14:17:00.004+09:002009-04-26T14:29:11.139+09:00Guido自伝 - 第二部, CNRI以降<p>原文:<a href="http://python-history.blogspot.com/2009/01/personal-history-part-2-cnri-and-beyond.html">http://python-history.blogspot.com/2009/01/personal-history-part-2-cnri-and-beyond.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>前回投稿したときに触れたPythonワークショップの後に、CNRI(the Corporation for National Research Initiatives)のモバイルエージェントに関する仕事をしないか、というオファーが来た。CNRIはヴァージニア州のレストンにある非営利の研究ラボである。私は1995年4月にそこに参加した。CNRIのディレクターのBob Kahn氏は初めて、PythonとLispの共通点がどれぐらいあるか、という点について私に指摘をした。もちろん、PythonとLISPは外見の文法上はまったく異なるが。CNRIにおけるPythonの仕事は、DARPAが資金を提供するモバイルエージェントの研究からの間接的な資金援助を受けることとなった。DARPAはPythonを使用したプロジェクトをいくつもサポートしてくれたが、Pythonそのものの開発に対する直接のサポートはそれほどなかった。</p>
<p>CNRIでは、私はピュアPythonで書かれたモバイルエージェントシステムの構築を行う小さな開発者のチームの責任者をまかされ、メンバー集めも行った。最初のチームメンバーであるRoger Masse氏とBarry Warsaw氏はNISTでのPythonワークショップでPythonのバグに文句を言っていたメンバーである。それに加え、PythonコミュニティのメンバーであるKen Manheimer氏、Fred Drake氏も雇い入れた。MITの卒業生で、もともとテキスト検索の業務のために雇用されていたJeremy Hylton氏もチームに加わった。発足時はTed Strollo氏がチームを率いた。後にAl Vezza氏に変わった。</p>
<p>このチームは、私が追加のPythonコミュニティのインフラを作ったり、維持したりするのを助けてくれた。おかげでpython.orgのウェブサイトやCVSサーバ、そしてさまざまなPythonのSIG(特定のテーマを扱うグループ)などを作ることができた。Pythonのバージョン1.3から1.6まではCNRIからリリースされた。Python 1.5.2というバージョンは長い間、もっとも人気があり安定したバージョンであった。</p>
<p>GNU mailmanもここで誕生した。私は当初、Perlで書かれたMajordomoと呼ばれるツールを使用していたが、Ken ManheimerがMajordomoのメンテナンスができないということに気づいてPythonを使った解決策を探した。彼はJohn Viega氏が書いたシステムを見つけてメンテナンスを引き継いだ。Ken氏がCNRIを離れDigital Creationsに移った後は、Barry Warsaw氏が引き継いだ。最終的にはフリーソフトウェア財団がこれを評価してくれて、公式のメーリングリストツールとして採用されることになった。そのため、Barry氏はこれのライセンスをGPL(GNUパブリックライセンス)にした。</p>
<p>Pythonワークショップは最初は年に2回というペースで続いていたが、規模が拡大したり、移動が大変であるという理由から、すぐに年に一度のイベントになった。最初はイベントを開催したいと思った組織が運営を行ってきた。例えばNIST(初回), USGS(2回目、3回目)、LLNL(年に一度になった4回目)などの組織が運営を行った。最終的にはCNRIが組織を引き継ぎ、後には(WWW&IETFカンファレンスとともに)商業的にイベントを行うFortecとしてスピンオフすることになった。参加者はすぐに数100人にふくれあがった。私がCNRIを去ってFortecがイベントに関与しなくなった後は、オライリー主催のオープンソースカンファレンス(OSCON)と同時開催という形で、国際Pythonカンファレンスが開催された。しかし、同時に、Pythonソフトウェア財団(後で説明する)はPyConという新しい草の根のカンファレンスを開始した。</p>
<p>私たちは最初のPythonの(ゆるい)組織をCNRIの中に作った。Mike McLay氏とPaul Everitt氏は「Python財団」を作ろうと努力したが、計画は流砂に飲み込まれるかのように中断してしまった。Bob Kahn氏は「Pythonソフトウェアアクティビティ」を作ろうと持ちかけてきたが、これは法律上の独立性には問題があったが、CNRIの法律の傘下での(非営利の)活動をシンプルにしたようなものだった。PythonソフトウェアアクティビティはPythonユーザがコミットする大きなグループを集めるのには成功したが、独立性が欠けていたために、活動が制限されてしまっていた。</p>
<p>CNRIはJPythonの開発の資金面でのサポートのために、DARPAの協力を得た。JPythonは後にJythonと名前が縮められた。JPythonはJavaで書かれたJavaのためのPython実装であり、当初はMITの卒業制作の一環として、Jim Hugunin氏が開発していた。彼はこの仕事を完成させるために雇って欲しいというのをCNRIを納得させた。私の休暇中のできごとなので、もしかしたら逆にCNRIがJim氏に対して参加するように説得したのかもしれないし、明確なことは分からない。2年後にJim氏がXeroxのPARCで行われているAspectJプロジェクトに参加するためにCNRIを離れると、Barry Warsaw氏がJPythonの開発を引き継いだ。これからしばらく後の話になるが、Jim氏はPythonをMicrosoftの.NETに移植したIronPythonの実装も行った。また数値計算モジュールのNumeric Pythonの最初のバージョンも作成した。</p>
<p>Pythonを使用する他のプロジェクトも、CNRIでいくつか開始された。このプロジェクトの参加者の中から何人かの新しいPythonのコア開発者が現れた。特に、MEMS Exchangeプロジェクトで働いていたAndrew Kuchling, Neil Schemenauer, Greg Wardの3名である。Andrew氏はCNRIに参加する前からPythonに貢献をしていた。彼が最初に行った大きなプロジェクトはサードパーティのライブラリのPythonの暗号化ツールキットである。これは数多くの基本的な暗号化アルゴリズムをPythonユーザに提供するものである。</p>
<p>Pythonの成功の原動力となったのは、CNRIが、DARPAのような研究の補助金のような形ではなく、Pythonの開発を支援するというモデルを作ろうとしたことである。私たちはXコンソーシアムにならい、Pythonコンソーシアムを作り、最低参加費用として20,000ドルという金額を設定した。しかし、ヒューレットパッカード社の1法人以外の協力を得ることができず、コンソーシアムの構想は頓挫してしまった。次の開発基金の供給元として候補にあがったのが、DARPAの援助を受けていたプログラミング教育プロジェクトであるCP4E(Computer Programming For Everybody)だった。しかし、この基金もチームのすべてをまかなうには不十分であった。何年もの期間にわたって費用負担をまかなえる年配者(卒業生?)のネットワークがあるということがわかった。それは私が援助を受けられるものではなかったため、私は他の選択肢を探し始めた。</p>
<p>ドットコムバブルがはじけた(まだ完全にはじけたわけではなかったが)2000年ごろ、私とCNRIのPythonチームのうちの3人(Barry Warsaw氏, Jeremy Hylton氏, Fred Drake氏)はBeOpen.com社に移籍することを了承した。この組織はオープンソース開発者を雇用していたカリフォルニアのベンチャー企業であった。PythonコミュニティのキーメンバーのTim Peters氏も私たちに合流した。</p>
<p>BeOpen.comへの移籍にともなって予想されたことは、Pythonの将来の所有権をどうするのかが難しくなったということである。CNRIはライセンスを変更し、私たちに新しいライセンスの元でPython 1.6をリリースするように要求してきた。私がCWIにいた頃に使用してきたライセンスは、MITライセンスであった。CNRIでリリースされた時に使用したライセンスは、このライセンスに「CNRIは責任を放棄する」という一文を追加しただけの、基本的に同じライセンスであった。しかし、1.6のライセンスはCNRIの弁護士が「弁護士語」で作成した長ったらしいものになってしまった。</p>
<p>我々はフリーソフトウェア財団のRichard Stallman氏とEben Moglen氏とともに、この新しいライセンスについて何度も長い議論を行った。彼らは、そのライセンスがGPLと互換性がなく、すでにFSFには欠かせないツールになっていたmailmanが使用できなくなってしまうことに危機感を覚えた。Eric Raymond氏の協力も得て、CNRIのPythonのライセンスはFSF, CNRIの双方を満足させられるものに変更された。結果としてできたものは理解するのが難しくなってしまったが、私の口から良くなったと唯一言えることは、オープンソース・イニシアティブから正当なオープンソースライセンスであるというお墨付きをもらえたことである。その後は問題なく所有権の変更が2度行われた。最初はBeOpen.comで、その後はPythonソフトウェア財団である。しかし、実際にはCNRIの弁護士の立ち会いの下で行われた。</p>
<p>このような立ち上げの苦労も数多くあり、BeOpen.comのビジネス計画は派手に失敗してしまった。多くの負債を抱え、いくつかの役員の疑わしい行動もあり、私のチーム以外の何人もの開発者を失望させることとなった。</p>
<p>私のチームは幸運なことに、PythonLabsとして名前が知れ渡っていたために、強い引き合いがあった。Pythonをビジネスとして最初に使用した会社の一つであるDigital Creations社にチームごと雇われることとなった。Ken Manheimer氏は私たちよりも何年も前からここで働いていた。Digital Creations社はすぐに、自社の主なオープンソース製品のZopeにあわせて、Zope Corporationと名前を変更した。Zopeはウェブのコンテンツ管理システムである。Zopeの創始者のPaul Everitt氏とRob Page氏はNISTで行った最初のPythonワークショップの参加者であり、Jim Fulton氏がCTOをしていた。</p>
<p>Digital Creations社以外には、VA Linux社とActiveState社からもオファーを受けいていて、選択次第ではPythonの歴史は大きく違ったものになっていただろう。VA Linux社は株式市場の新星であったが、一時的にEric Raymond氏を書類上だけ大金持ちにした後は、最終的には株価は劇的に下がることとなった。振り返ってみると、創始者のDick Hardt氏が議論好きということを抜きにすれば、ActiveState社も悪い選択肢ではなかったかもしれないと思う。会社の場所がカナダでなければ、という前提の上であるが。</p>
<p>2001年に非営利組織のPythonソフトウェア財団を創設した。初期の構成メンバーは、その時点でPythonに貢献していた主な開発者たちである。Eric Raymond氏はその組織の出資者の一人である。この時期のことに関しては、また別の機会に書かなければならないと思っている。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-64283419855506456412009-04-26T10:28:00.003+09:002009-04-26T10:33:54.394+09:00Guido自伝 - 第一部, CWI<p>原文:<a href="http://python-history.blogspot.com/2009/01/personal-history-part-1-cwi.html">http://python-history.blogspot.com/2009/01/personal-history-part-1-cwi.html</a><br/>
原文投稿者:Guido van Rossum</p>
<p>Pythonの初期の開発は、<a href="http://www.cwi.nl/">CWI</a>と呼ばれる、オランダのアムステルダムにある研究施設で始まった。CWIはオランダ語の単語の頭文字を集めたもので、訳すとすれば、「数学&コンピュータ科学センター」ということになる。CWIはオランダの教育省と、他の研究の助成金によって運営されていて、アカデミックなレベルでコンピュータサイエンスと数学を研究する、とても面白い場所である。研究をしている多くの博士課程の学生と、「数学センター」というオリジナルの名前をいまだに覚えているOBの職業の専門家がいつでもそこに在籍している。当時の組織名は<a href="http://en.wikipedia.org/wiki/ALGOL_68">Algol 68</a>の開発で良く知られていた思う。</p>
<p>私は大学を卒業した1982年の後半からCWIで働き始めた。<a href="http://en.wikipedia.org/wiki/Lambert_Meertens">Lambert Meertens氏</a>と<a href="http://en.wikipedia.org/wiki/Steven_Pemberton">Steven Pemberton氏</a>が率いていた、<a href="http://ja.wikipedia.org/wiki/ABC_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%A8%80%E8%AA%9E)">ABC</a>グループにプログラマとして入った。4~5年後にめざましい成功を収めることなくABCプロジェクトが中断されてしまった後は、<a href="http://www.huygens.org/sape/">Sape Mullender氏</a>が率いていたCWIの<a href="http://ja.wikipedia.org/wiki/Amoeba">Amoeba</a>グループに異動となった。Amoebaというのは、マイクロカーネルベースの分散システムで、大学教授の<a href="http://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%B3%E3%83%89%E3%83%AA%E3%83%A5%E3%83%BC%E3%83%BB%E3%82%BF%E3%83%8D%E3%83%B3%E3%83%90%E3%82%A6%E3%83%A0">Andrew Tanenbaum氏</a>がリーダーとなって、CWIと<a href="http://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%A0%E3%82%B9%E3%83%86%E3%83%AB%E3%83%80%E3%83%A0%E8%87%AA%E7%94%B1%E5%A4%A7%E5%AD%A6">アムステルダム自由大学</a>が共同で開発を行っていたプロジェクトである。1991年、Sape氏が<a href="http://en.wikipedia.org/wiki/University_of_Twente">トゥエンテ大学</a>の教授になるためにCWIを離れると、<a href="http://homepages.cwi.nl/%7Edcab/">Dick Bulterman氏</a>が率いる、新しくできたCWIマルチメディアグループに最終的に落ち着いた。</p>
<p>PythonはCWIにおける私のすべての経験から生み出されたものである。今振り返ってみると、ABCのプロジェクトはPythonのキーとなるインスピレーションを、Amoebaプロジェクトでは開発に直結する大切なモチベーションを与えてくれた。マルチメディアグループではそれらをさらに成長させてくれた。しかし、私の知る限り、CWIではPythonの開発に対して公式に予算が計上されることはなかった。しかし、Pythonは、Amoebaとマルチメディアグループの両方の中で重要なツールとして使用され、発展していった。</p>
<p>私がPythonを作成する最初のモチベーションとなったのは、Amoebaプロジェクトの中で高次元の言語が必要とされているという認識からであった。システム管理ユーティリティの開発をC言語で行うと、時間がとてもかかることを実感していた。それに加えて、これらをBourneシェルでこれらの開発を行うとしたが、様々な理由からうまくいかなかった。もっとも重大な理由の一つは、Amoebaが根本から新しい概念の分散マイクロカーネルシステムであったため、Amoebaのプリミティブなオペレーションは、Bourne shell上で行える伝統的なプリミティブなオペレーションと大きく異なっている(Amoebaの方が粒度が細かい)。そのため、「C言語とシェルスクリプトの間のギャップを橋渡しをする」ことができる言語のニーズがあったのである。これはしばらくの間、Pythonを紹介するときによく使われるキャッチフレーズとなった。</p>
<p>この点に関して、「なぜ既存の言語を移植しなかったのか?」と疑問をもたれる思う。しかし、私の視点からは、この目標に合致する言語は、当時はそれほど多くはなかったように見えた。私はPerl3には慣れ親しんでいたが、Bourneシェル以上にUNIXの環境と結びついていた。また、私がPerlの文法を好きになれなかったのも理由のひとつである。プログラミング言語の文法に関して、私に強く影響を与えた言語は<a href="http://ja.wikipedia.org/wiki/Algol">Algol60</a>, Pascal, Algol68などの言語である。これらの言語はすべて、私がその時に学んできたものである。そして、私の人生の4年間という期間を費やしてきたABCの影響も無視はできない。そのため、これはいいと私が思ったABCの要素はすべて取り込んだオリジナルの言語を設計したいと思っていた。同時に、私が気づいたABCの欠点もすべて修正したいと思った。</p>
<p>私が最初に修正しようとした問題は、プログラミング言語の名前であった。実際の所、ABCチームは言語の名前選びで苦労をした。当初ついていた言語名は"B"であったが、もっと古くて有名な他の同名のプログラミング言語のBがあり、まぎらわしかったために使えなくなってしまったのである。また、別の理由として、<i>B</i>という名前が作業中の名前である、という意味あいもあった。これは、<i>B</i>というのは言語名を入れる変数の名前であるというジョークであった(そのため、この記事の中ではイタリックにしてある)。ABCチームは、新しい名前を命名する公開コンテストを実施した。しかし、合格ラインを超えた応募はなく、結局予備のためにチーム内で用意していた候補から選ばれることとなった。プログラミングを「ABCと同じぐらい簡単にする」という意味を込めた名前であったが、私から見ても、多くの点で有名無実であると思ったものである。</p>
<p>そのようなことがあったため、命名に関しては、考えすぎた名前をつけるよりも、あまり考えないで行った方が良さそうだと考えた。私は最初に心に思い浮かんだものから名前を取った。それは私が好きなコメディグループ「<a href="http://ja.wikipedia.org/wiki/%E7%A9%BA%E9%A3%9B%E3%81%B6%E3%83%A2%E3%83%B3%E3%83%86%E3%82%A3%E3%83%BB%E3%83%91%E3%82%A4%E3%82%BD%E3%83%B3">空飛ぶモンティ・パイソン</a>」からの発想だった。そもそもPythonの開発は正規のプロジェクトではなくて、こっそりと行われる"<a href="http://ja.wikipedia.org/wiki/%E3%82%B9%E3%82%AB%E3%83%B3%E3%82%AF%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9">スカンクワークス</a>プロジェクト"であったため、コメディから名前を取るぐらいの悪ふざけさ加減がちょうどいいと思ったのである。"Python"という言葉は覚えやすく、多少粋な感じであったし、プログラミング言語の名前は人物から付けるという伝統(Pascal, Ada, Eiffel)にも合っている。モンティ・パイソンチームは科学技術の分野の進歩に貢献したという名声を得てはいないと思うが、ギークが喜んでくれるものを提供できたと思う。CWIのAmoebaグループもTV番組の名前にちなんだプログラム名をつける伝統があったので、Pythonという名前はこれともフィットしている。</p>
<p>このように決めた名前であったので、私は何年もの間、Pythonという名前と蛇とを結びつけようという活動には抵抗をしてきた。しかし、オライリーが最初のPythonの書籍「Pythonプログラミング」の表紙に蛇のイラストを描こうとしたときに、この抵抗をあきらめることにした。動物の絵を使用するのがオライリーの伝統であったが、もし動物でなければならないのであれば、蛇であってもいいのではないかと思ったのである。</p>
<p>名前の問題が決着し、私がPythonの開発業務を開始したのは1989年の12月の末頃であった。1990年の最初の月には動作可能なバージョンができあがった。この作業のメモは残していないが、"pgen"と呼んでいたシンプルなLL(1)パーサジェネレータの実装からPythonを書き始めたのを鮮明に覚えている。このパーサジェネレータは現在でもPythonのソースコード実装の一部として含まれているし、すべてのコードの中ではあまり変更されていない部分であると思う。1990年にはCWIの何人かのメンバーが初期バージョンのPythonを使用し始めた。Amoebaグループ以外の人も使用した。同僚でもあるプログラマーの<a href="http://homepages.cwi.nl/%7Esjoerd/">Sjoerd Mullender氏</a>(Sape氏の弟である)と、私がCWIを離れた後も何年もMacintoshへの移植のリードプログラマーを引き受けてくれることになる<a href="http://homepages.cwi.nl/%7Ejack/">Jack Jansen氏</a>の2名が、私と一緒に開発に携わった主要な開発者である。</p>
<p>1991年2月20日に、私は<a href="http://www.faqs.org/faqs/alt-sources-intro/">alt.sourcesニュースグループ</a>上で、世界に向けてPythonを初めて公開した。21分割された<a href="http://ja.wikipedia.org/wiki/Uuencode">uuencode</a>されたファイルを結合し、uudecodeをするとtarファイルが作成できるというものであった。この時のバージョンは0.9.0と付けられ、X11プロジェクトが使用していた、MITライセンスの亜種のライセンスの元に公開された。法的に責任を持てる団体として、CWIの親会社である"Stichting Mathematisch Centrum"の名前で公開された。それまで私が作成してきたプログラム同様、Pythonもまた<a href="http://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%AA%E3%83%83%E3%82%AF%E3%83%BB%E3%83%AC%E3%82%A4%E3%83%A2%E3%83%B3%E3%83%89">Eric Raymond氏</a>と<a href="http://ja.wikipedia.org/wiki/Bruce_Perens">Bruce Perens氏</a>が1997年の終わり頃にオープンソースという用語を作り出す以前から、オープンソースであった。</p>
<p>公開するとすぐに多くのフィードバックがあった。これに励まされるようにして、これから何年もの間に一定のペースで次々とリリースを行った。ソースコードの変更を記録するのと、Sjoerd氏、Jack氏とコードの責任を共有するために<a href="http://ja.wikipedia.org/wiki/Concurrent_Versions_System">CVS</a>を使用し始めた。偶然にも、Pythonと同様にCVSも、ABCグループの初期メンバーである<a href="http://en.wikipedia.org/wiki/Dick_Grune">Dick Grune氏</a>によってシェルスクリプト集として開発されていた。当時はWebはまだなかったが、私はFAQを書き、当時のFAQの慣習に従っていくつかのニュースグループに定期的にポストしていた。メーリングリストも開始した。1993年の3月にはうれしいことに、私が直接関与しないかたちで<a href="http://groups.google.com/group/comp.lang.python/topics">comp.lang.pythonニュースグループ</a>が作成された。ニュースグループとメーリングリストは、現在でも稼働している双方向のゲートウェイを通じて統合された。当時大きなシェアを持っていたオープンソースのメーリングリスト管理システムのmailmanにはこのような機能はなかったため、このゲートウェイはPythonで作成された。</p>
<p>1994年の夏に、ニュースグループ上で「<a href="http://www.python.org/search/hypermail/python-1994q2/1040.html">もしGuido氏がバスに轢かれたら?</a>」というタイトルのスレッドがニュースグループをにぎわした。これは私個人の貢献に、Pythonのコミュニティの成長が依存していたというのが発端である。この結果として、Michael McLay氏から招待を受けて、2ヶ月間、客員研究者としてNIST(アメリカ国立標準技術研究所)に行くことになった。<a hre="http://www.nist.gov/">NIST</a>(<a href="http://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%A1%E3%83%AA%E3%82%AB%E5%9B%BD%E7%AB%8B%E6%A8%99%E6%BA%96%E6%8A%80%E8%A1%93%E7%A0%94%E7%A9%B6%E6%89%80">wikipedia</a>)はメリーランド州のゲーサーズバーグにあり、以前は国立標準局と呼ばれていた。Michael氏はNIST内に、多くのPythonに興味を持つ「顧客」を持っていた。彼らは標準化に関するさまざまなプロジェクトにPythonを使用したいと考えていた。Micheal氏は私が彼らのPythonのスキルアップの手助けに必要であるという目的で、私の滞在費の予算を確保してくれた。可能であれば彼らのニーズに従ってPythonを改善するというのもその目的に含まれていた。</p>
<p>1994の11月、私がNISTの滞在中に、NISTのプログラマの<a href="http://en.wikipedia.org/wiki/Ken_Manheimer">Ken Manheimer氏</a>の多大な援助と励ましによって、<a href="http://www.python.org/workshops/1994-11/attendees.pics.html">最初のPythonワークショップ</a>が開催された。およそ20名の参加者がいたが、そのうちの半数は現在もPythonのコミュニティ活動にアクティブに参加している。何人かのメンバーはオープンソースプロジェクトのリーダーになっている(<a href="http://www.zope.org/">Zope</a>の<a href="http://www.zope.com/about_us/management/james_fulton.html">Jim Fulton氏</a>と、<a href="http://en.wikipedia.org/wiki/GNU_Mailman">GNU mailman</a>の<a href="http://barry.warsaw.us/">Barry Warsaw氏</a>)。NISTのサポートにより、サンタフェで開催されたUsenix Little Languagesカンファレンスで、400人もの人の前でキーノートを発表することもできた。このカンファレンスを主催した<a href="http://en.wikipedia.org/wiki/Tom_Christiansen">Tom Christiansen氏</a>は、気さくなPerl支持者であり、Perl作者の<a href="http://ja.wikipedia.org/wiki/%E3%83%A9%E3%83%AA%E3%83%BC%E3%83%BB%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB">Larry Wall氏</a>とTcl/Tk作者の<a href="http://home.pacbell.net/ouster/">John Ousterhout氏</a>を紹介してくれた。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-52086394323072532632009-04-24T20:06:00.004+09:002009-04-24T20:12:55.187+09:00Pythonの沿革<p>原文: <a href="http://python-history.blogspot.com/2009/01/brief-timeline-of-python.html">http://python-history.blogspot.com/2009/01/brief-timeline-of-python.html</a><br/>
原文投稿者: Guido van Rossum
</p>
<p>Pythonの開発がスタートしたのは、Tcl, Perl, Ruby(これはPythonよりも遅い誕生であるが)など、多くの他の動的(で、オープンソース)なプログラミング言語が活発に開発され、人気を獲得しつつある時期であった。Pythonを適切な歴史観で語る一助になると思うので、Pythonのリリースの歴史を以下のリストにまとめた。すべてのイベントをきちんと記録してきたわけではないので、初期の日時は多少あいまいな部分もある。</p>
<table>
<tr><th>リリース日時</th><th>バージョン</th></tr>
<tr><td>1989年12月</td><td>実装開始</td></tr>
<tr><td>1990年</td><td>CWI(オランダの国立情報工学・数学研究所)<br/>内での内部リリース</td></tr>
<tr><td>1991年2月20日</td><td>0.9.0(ニュースグループのalt.sourcesでリリース)</td></tr>
<tr><td>1991年2月</td><td>0.9.1</td></tr>
<tr><td>1991年秋</td><td>0.9.2</td></tr>
<tr><td>1991年12月24日</td><td>0.9.4</td></tr>
<tr><td>1992年1月2日</td><td>0.9.5(Macintoshのみ)</td></tr>
<tr><td>1992年4月6日</td><td>0.9.6</td></tr>
<tr><td>1992年(時期不明)</td><td>0.9.7beta</td></tr>
<tr><td>1993年1月9日</td><td>0.9.8</td></tr>
<tr><td>1993年7月29日</td><td>0.9.9</td></tr>
<tr><td>1994年1月26日</td><td>1.0.0</td></tr>
<tr><td>1994年2月15日</td><td>1.0.2</td></tr>
<tr><td>1994年5月4日</td><td>1.0.3</td></tr>
<tr><td>1994年7月14日</td><td>1.0.4</td></tr>
<tr><td>1994年10月11日</td><td>1.1</td></tr>
<tr><td>1994年11月10日</td><td>1.1.1</td></tr>
<tr><td>1995年4月13日</td><td>1.2</td></tr>
<tr><td>1995年10月13日</td><td>1.3</td></tr>
<tr><td>1995年10月25日</td><td>1.4</td></tr>
<tr><td>1998年1月3日</td><td>1.5</td></tr>
<tr><td>1998年10月31日</td><td>1.5.1</td></tr>
<tr><td>1999年4月13日</td><td>1.5.2</td></tr>
<tr><td>2000年9月5日</td><td><a href="http://www.python.org/download/releases/1.6/">1.6</a></td></tr>
<tr><td>2000年10月16日</td><td><a href="http://www.python.org/download/releases/2.0/">2.0</a></td></tr>
<tr><td>2001年4月17日</td><td><a href="http://www.python.org/download/releases/2.1/">2.1</a></td></tr>
<tr><td>2001年12月21日</td><td><a href="http://www.python.org/download/releases/2.2/">2.2</a></td></tr>
<tr><td>2003年7月29日</td><td><a href="http://www.python.org/download/releases/2.3/">2.3</a></td></tr>
<tr><td>2004年11月30日</td><td><a href="http://www.python.org/download/releases/2.4/">2.4</a></td></tr>
<tr><td>2006年9月16日</td><td><a href="http://www.python.org/download/releases/2.5/">2.5</a></td></tr>
<tr><td>2008年10月1日</td><td><a href="http://www.python.org/download/releases/2.6/">2.6</a></td></tr>
<tr><td>2008年12月3日</td><td><a href="http://www.python.org/download/releases/3.0/">3.0</a></td></tr>
</table>
<p>現在でもpython.org上でPRされているリリースにはハイパーリンクを貼っておいた。ここでは書いていないが、多くのリリースに対して、2.0.1といったいくつかの小さいリリースも行われている。しかし、細かいリリースまで表に入れてしまうとリストが長くなりすぎてしまうため、省略してある。非常に古いソースのアーカイブファイルも、<a href="http://www.python.org/ftp/python/src/">http://www.python.org/ftp/python/src/</a>にて現在もアクセスすることができる。古いさまざまなバイナリのリリースや、それ
以外の歴史的なものも、このフォルダの上位階層で見つけることが可能である。
</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0tag:blogger.com,1999:blog-6018259859220218948.post-774467545829145712009-04-24T07:50:00.004+09:002009-04-24T08:13:26.010+09:00Pythonの設計哲学<p>原文: <a href="http://python-history.blogspot.com/2009/01/pythons-design-philosophy.html">http://python-history.blogspot.com/2009/01/pythons-design-philosophy.html</a><br/>
原文投稿者: Guido van Rossum
</p>
<p>今後のブログのエントリーは、生々しいPythonの歴史の詳細に入り込んでいく予定である。しかし、それに触れる前に、私がPythonの設計や実装をしている時に、意志決定を助けてくれた哲学的なガイドラインについて詳しく説明をしていきたいと思う。</p>
<p>まず最初に、Pythonはもともと"スカンク・ワークス(社内の秘密裏のプロジェクトの意味)"として計画がスタートした。公式な予算などなかったし、私は素早く結果を出そうとしていた。マネジメントにプロジェクトのサポートを説得する、というのがその理由の一つである(そして、その目論見は達成できた)。このような状況から、時間を節約するためのルールがいくつか導き出された。</p>
<ul>
<li>道理に叶うときはいつでも、他の場所からアイディアを借りてくる。</li>
<li>「物事は可能な限り単純化されるべきである。ただし、それ以上単純にしてはいけない」(アインシュタイン)</li>
<li>一つのことに集中する(UNIXの哲学)</li>
<li>パフォーマンスについては気にしないで。必要であれば、後から最適化を行うので。</li>
<li>環境に戦いを挑むな。そして流れに身を任せよ。</li>
<li>完璧を求めようとするな。「十分に良い」で足りることがほとんどである。</li>
<li>(それゆえに)たまに手を抜くのは問題はない。特に、後でやれば正しくできる場合には。</li>
</ul>
<p>これ以外の原則は時間の節約を意図したものではなかった。たまに正反対なことを言っているものも含まれていた。</p>
<ul>
<li>Pythonの実装は特定のプラットフォームに縛り付けるべきではない。いくつかの機能が動作しないのは問題ないが、コアはどこでも動作すべきである。</li>
<li>コンピュータが行えるような細かい仕事はユーザにさせてはならない。(私はいつもこの原則に従っていたわけではなく、後のセクションでこれの悲惨な影響についていくつか説明する)。</li>
<li>プラットフォームに依存しないユーザコードをサポートし、また、そうなるように奨励すべきである。ただし、プラットフォームの能力や特性を生かすためのアクセスを妨げてはならない。(これはJavaとは対照的である)。</li>
<li>巨大で複雑なシステムは、さまざまな階層で拡張可能であるべきだ。きれいに拡張できる場合もあるだろうし、洗練したやり方ができないこともあるだろうが、これをすることで、ユーザが自分自身を助ける機会を最大限に増やすことができる。</li>
<li>エラーは致命的であってはならない。エラーの状況であっても、バーチャルマシンの機能が壊れていなければ、ユーザコードはエラーから復帰できるようにすべきである。</li>
<li>同時に、エラーはこっそり握りつぶしてはならない。(実装時には、これらの2つの項目により、例外を使用するという意志決定が自然に行われた)</li>
<li>ユーザのPythonコードのバグにより、Pythonのインタプリタが未定義な動作を起こしてはならない。コアダンプは、決してユーザの責任ではない。</li>
</ul>
<p>最終的に、私は良いプログラミング言語設計のためのさまざまなアイディアを身につけることができた。このアイディアの多くを学んだきっかけは、私が初めて実際の言語の実装と設計を体験をしたABC(訳注:教育用のプログラミング言語の名前)のグループに参加したことである。これらのほとんどのアイディアは、エレガンス、シンプルさ、読みやすさなど、主観的な概念を中心に展開されているため、形式知に表出化するのが困難であった。</p>
<p>後ほど、ABCがPythonに与えた影響について詳しく述べるが、まずは読みやすさのルールについて説明してみたい。まず、句読記号文字は、一般的な英語的な記述や、高校レベルの代数に沿った、伝統的な使い方をすべきである。ただし、かけ算の"x*y"、配列アクセスの"a[i]"、属性アクセスの"x.foo"など、プログラミング言語の中で長い間使用されてきた表記法がある場合は例外とすることもある。ただし、Pythonでは変数を明示するために"$"を使用したり、副作用のある操作を明示するために"!"を使用することはない。</p>
Tim Petersは古くからのPythonユーザである。最終的にもっとも多くのコミットをする、頼りになるコア開発者となった。彼は、私が言語化してこなかった設計原理を記録しようとして、<a href="http://www.python.org/dev/peps/pep-0020/">"Zen of Python"</a>(リンク先は英語)と呼ばれるものを作成した。全文を引用する。</p>
<ul>
<li>醜さよりも美しさ</li>
<li>不言実行よりも有言実行</li>
<li>複雑よりもシンプル</li>
<li>入り組んだ1行よりも、複数行のコード</li>
<li>深い階層よりも平坦な階層</li>
<li>過密なコードよりも疎なコード</li>
<li>読みやすさに勝るものなし</li>
<li>「特別な場合」というのは言い訳にならない</li>
<li>しかし、ルールに愚直であるよりは実用性</li>
<li>問題があるときには、こっそりと処理してはならない</li>
<li>隠すすることが明示されている場合を除いて</li>
<li>解釈が多数ある場合、推測でやってはならない</li>
<li>実現する方法は一つ、なるべく一つであるべきだ</li>
<li>オランダ人※にしか明確でないこともありえるが</li>
<li>「実現してないいつか」 よりも「今」</li>
<li>あわてて今やるよりはしない方がいいことも多い</li>
<li>説明が大変なら、それは悪いアイディアだ</li>
<li>説明が簡単なら、それはいいアイディアだろう</li>
<li>名前空間はすばらしいアイディアだ<br/>それよりもすごいことをやろう!</li>
</ul>
<p>※訳注: おそらくPython作者のGuidoのこと</p>
<p>ABCにおける私の経験はPythonにとても大きな影響を与えたが、ABCグループの設計原理の中には、Pythonのものと根本的に異なるものがいくつか存在する。これらに関しては、Pythonは意図的に違う方向を目指している。</p>
<ul>
<li>ABCグループは完璧性を求めて努力していた。例えば、ABCでは、大きいコレクションでの性能を改善するために、ツリーを元にしたデータ構造のアルゴリズムを使っていた。しかし、これは小さなコレクションについては良くなかった。</li>
<li>ABCグループでは、「大きくて、悪いものがたくさん存在するコンピュータの世界」からユーザをなるべく完璧に隔離しようとしていた。数値の格納できる範囲や、文字列の長さ、コレクションのサイズの限界(メモリの限界を除き)だけでなく、ファイルやディスクを扱って「保存する」といったことや、他のプログラムを扱う必要性からもユーザを遠ざけようとしていた。ABCは必要なモノがすべて手に入る唯一のツールであろうとした。このため、ABCグループではABCに特化した、完全に統合された編集環境を必要とするまでになった。結果的には、ABCの環境から逃げる方法もないことはなかったが、言語から直接アクセスすることはできなかった。</li>
<li>ABCグループでは、ユーザはコンピュータの経験はまったくない(もしくはそれを忘れようとしている)という想定をしていた。そのため、標準的なプログラミング用語よりも、「新しい人にとって親しみやすい」という別の用語が導入された。例えば、手続きは"手引き(how-tos)"、変数は"場所"とされました。</li>
<li>ABCグループでは、進化の道筋というのを考慮しないでABCを設計した。言語の設計の過程の中では、ユーザの参加というのは期待されていなかった。ABCはクローズなシステムとして、設計者ができるかぎり完璧なものが作成された。ユーザが「ボンネットの中を調べる」ようなことは推奨されていなかった。プロジェクトの後半には、実装されたプログラムの一部を先進的なユーザ公開しようという話も出てきたが、この話が実現することはなかった。</li>
</ul>
<p>様々な意味で、Pythonをここまで成功させてきた主な理由の一つが、Pythonを開発するときに私が使用してきたこれらの設計哲学であったと思う。例え完璧を目指さなくても、アーリー・アダプターの人たちの目的を達成するのに、Pythonは「十分に良い」働きをしてきた。ユーザ基盤が成長してくるにつれて、ユーザから出される改善要望が徐々に言語に取り込まれてきた。後のセクションで解説していくが、多くの改良により多くの部分の変更や、言語のコア部分の作り直しが行われた。現在でも、Pythonは改良され続けている。</p>SHIBUKAWA Yoshikihttp://www.blogger.com/profile/07207061290062069448noreply@blogger.com0