デザインと歴史 FAQ
******************


Python はなぜ文のグループ化にインデントを使うのですか？
=======================================================

Guido van Rossum の信じるところによれば、インデントによるグループ化は
非常にエレガントで、普通の Python プログラムを大いに読みやすくします。
しばらくすればほとんどの人はこの仕様を気に入るようになります。

開始/終了の括弧がないので、構文解析器と人間の読者の間にグループ化の解
釈の違いは起こりえません。時折、C のプログラマはこのようなコード片に出
くわします:

   if (x <= y)
           x++;
           y--;
   z++;

条件式が真のとき、 "x++" 行のみが実行されます。しかしインデントによっ
て、多くの人が別のことを考えてしまいます。経験豊富なCプログラマでさえ
、 "x > y" なのに "y" がデクリメントされるのはなぜだろうと、このコード
をしばらく凝視することがあります。

Python は開始/終了の括弧がないので、コーディングスタイルの争いに余り影
響されません。C言語では中括弧の置き方についてさまざまな流儀があります
。特定のスタイルを使ってコードを読み書きするのに慣れたあと、別のスタイ
ルでコードを読んだり(あるいは書く必要に迫られたり)するときに、何となく
心配になるのはよくあることです。

多くのコーディングスタイルは begin/end の括弧にそれぞれ一行を使います
。これではプログラムは冗長になって画面を浪費し、プログラムの見通しが悪
くなります。一つの関数は一画面 (例えば 20 から 30 行) に収めるのが理想
です。20 行の Python は 20 行の C よりもはるかに多くの作業ができます。
これは begin/end の括弧がないからだけではありません -- 宣言が不要なこ
とや高レベルなデータ型もその理由です -- が、インデントに基づく構文は確
かに役に立っています。


なぜ単純な算術演算が奇妙な結果になるのですか？
==============================================

次の質問を参照してください。


なぜ浮動小数点数の計算はこんなに不正確なんですか？
==================================================

ユーザーはよく次のような結果に驚きます:

   >>> 1.2 - 1.0
   0.19999999999999996

Python のバグと考えるかもしれませんが、そうではありません。  この結果
に Python はほとんど影響しておらず、むしろ大きく関係しているのは下敷き
としているプラットフォームによる浮動小数点数の扱い方です。

CPython における "float" 型は C 言語の "double" 型をデータ格納先に使い
ます。  "float" オブジェクトの値は固定精度 (典型的には 53 bit) の 2 進
浮動小数点数で格納されます。  そして Python は浮動小数点演算を行うため
に C の演算を使いますが、これはプロセッサのハードウェア実装に依存しま
す。つまり、浮動小数点数に関して Python は C 言語や Java を含む多くの
一般的な言語と同じように振る舞います。

10 進数表記 (decimal) で簡単に表せる数値でも、その多くは 2 進浮動小数
点数 (binary) で正確に表現できません。  たとえば次では

   >>> x = 1.2

"x" に保存された値は 10 進数の "1.2" の (とても高い精度の) 近似値であ
って、厳密な "1.2" ではありません。一般的なコンピューターでは、実際に
格納される値は:

   1.0011001100110011001100110011001100110011001100110011 (binary)

で、正確には次の値です:

   1.1999999999999999555910790149937383830547332763671875 (decimal)

典型的な 53bit 精度は、Python の float に 10 進数での 15〜16 桁の正確
さを与えます。

詳しくは、Python チュートリアルの floating-point arithmetic の章を参照
してください。


なぜ Python の文字列はイミュータブルなのですか？
================================================

これにはいくつかの利点があります。

一つはパフォーマンスです。文字列がイミュータブルなら、生成時に領域を割
り当てることができるので、必要な記憶域は固定されて、変更されません。こ
れはタプルとリストを区別する理由の一つでもあります。

他の利点は、Python の文字列は数と同じくらい "基本的" なものと考えられ
ることです。8 という値を他の何かに変える手段が無いように、文字列
"eight" を他の何かに変える手段も無いのです。


なぜメソッドの定義や呼び出しにおいて 'self' を明示しなければならないのですか？
==============================================================================

このアイデアは Modula-3 から取り入れられました。これは様々な理由からと
ても便利だと言えます。

まず、ローカル変数ではなく、メソッドやインスタンス属性を扱っていること
がより明確になります。 "self.x" や "self.meth()" と書いてあれば、その
クラスの定義を憶えていなくても、それがインスタンス変数やメソッドである
ことは明らかです。C++ では、(グローバルが滅多になかったり、簡単に見分
けがつくなら) ローカル変数宣言がないことからある程度わかるでしょう。--
しかし Python にはローカル変数宣言がないので、クラス定義を調べて確かめ
なくてはなりません。C++ や Java のコーディングスタンダードに、インスタ
ンス属性に "m_" 接頭辞をつけるものがあるので、この明示性はそれらの言語
においても有用です。

第二に、特定のクラスからメソッドを明示的に参照または呼び出ししたい時に
、特別な構文が必要なくなります。C++ では、派生クラスでオーバーライドさ
れた基底クラスからメソッドを使うには、 "::" 演算子を使わなければなりま
せん。 -- Python では、 "baseclass.methodname(self, <argument list>)"
と書けます。これは特に、 "__init__()" メソッドに便利ですし、派生クラス
のメソッドが、基底クラスにある同じ名前のメソッドを拡張するために、基底
クラスのメソッドをどうにかして呼び出したい時にも便利です。

最後に、インスタンス変数に対する、代入の構文の問題を解決できます。
Python のローカル変数は、関数の中で (global が明示的に宣言されることな
く) 値が代入された変数 (と定義されています！) です。 なので、ある代入
が意図するのが、ローカル変数へではなくインスタンス変数への代入であると
、インタプリタが判断する手段が必要です。 そしてそれは構文を見るだけで
分かる方が (効率が) 良いのです。 C++ ではその区別を宣言時に行いますが
、Python には宣言がなく、この目的だけのために導入しなければならないの
は残念です。 "self.var" を明示すればうまく解決できます。 同様に、イン
スタンス変数を使うのにも "self.var" と書かなければならないので、メソッ
ド内の修飾のない名前を参照する際に、そのインスタンスの属性を検索する必
要がなくなります。 別の言い方をすれば、ローカル変数とインスタンス変数
は二つの異なる名前空間に存在し、Python にどちらの名前空間を使うかを伝
えなくてはならないのです。


式中で代入ができないのはなぜですか？
====================================

Python 3.8 以降ならできるよ!

セイウチ演算子 ":=" を使った代入式は、式の中で変数に代入します:

   while chunk := fp.read(200):
      print(chunk)

より詳しくは **PEP 572** を参照してください。


Python にメソッドを使う機能 (list.index() 等) と関数を使う機能 (len(list) 等) があるのはなぜですか？
====================================================================================================

Guidoいわく：

   （a） 幾つかの演算では、接頭辞は接尾辞よりも単純に読みやすいからで
   す。接頭辞（そして接中辞！）による演算は数学において長い歴史があり
   、そこでは課題に対する数学者の思考を視覚的に助けるような記法が好ま
   れます。x*(a+b)をx*a + x*bに書き換える容易さと、それと同じことを純
   粋なオブジェクト指向の記法で行う煩わしさを比較してみてください。

   （b） len(x) というコードを読んだ時、私はそれが何かの長さを問うてい
   るのだなと知ることができます。これは私に2つの事を知らせています。一
   つは結果が整数であること、そして引数は何らかのコンテナであることで
   す。対して、 x.len() を目にした場合、私はその時点でxが何らかのコン
   テナであり、それが標準のlen()を持っているクラスを継承しているか、イ
   ンターフェースを実装していることを知っている必要があります。
   mapping を実装していないクラスが get() や keys() メソッドを持ってい
   たり、 file でない何かが write() メソッドを持っているような混乱は時
   折見かけます。

   -- https://mail.python.org/pipermail/python-3000/2006-November/004
   643.html


join() がリストやタプルのメソッドではなく文字列のメソッドなのはなぜですか？
===========================================================================

文字列は Python 1.6 から他の標準型に大きく近づきました。それ以前は常に
string モジュールの関数を使ってできていたことと同等の機能を持つメソッ
ドがこの時に追加されました。その新しいメソッドの多くは広く受け入れられ
ましたが、一部のプログラマに不快を感じさせていると思われるものがこれで
:

   ", ".join(['1', '2', '4', '8', '16'])

結果はこうなります:

   "1, 2, 4, 8, 16"

この使い方には二つの議論があります。

一つ目は、「文字列リテラル (文字列定数) のメソッドを使うのは醜すぎる」
というようなものです。確かにそうかも知れませんが、文字列リテラルは単な
る固定された値に過ぎないというのが答えです。文字列に束縛された名前にメ
ソッドが許されるなら、リテラルに使えないようにする論理的な理由はないで
しょう。

二つ目の反論は、よく「シーケンスに対して、文字列定数を使って要素を結合
するように指示しているのだ」と表現されます。 残念ながら、そうではあり
ません。 なぜか "split()" が文字列のメソッドであることには、はるかに抵
抗が少ないようです。 次の例では、何を指示しているかが分かりやすいから
でしょう。

   "1, 2, 4, 8, 16".split(", ")

これは文字列リテラルに対する、与えられたセパレータ (または、デフォルト
では任意の空白文字の連続) で区切られた部分文字列を返せという指示です。

"join()" は、セパレータ文字列に、文字列のシーケンスをイテレートして隣
り合う要素の間に自身を挿入するように指示しているので、文字列のメソッド
です。このメソッドは、独自に定義された新しいクラスを含め、シーケンスの
規則を満たすいかなる引数にも使えます。バイト列やバイト配列にも同様のメ
ソッドがあります。


例外はどれくらい速いのですか？
==============================

"try"/"except" ブロックは例外が送出されなければ極端に効率的です。実際
に例外を捕捉するのは高価です。Python 2.0 より前のバージョンでは、この
イディオムを使うのが一般的でした:

   try:
       value = mydict[key]
   except KeyError:
       mydict[key] = getvalue(key)
       value = mydict[key]

これは、辞書がほとんどの場合にキーを持っていると予想できるときにのみ意
味をなします。そうでなければ、このように書きます:

   if key in mydict:
       value = mydict[key]
   else:
       value = mydict[key] = getvalue(key)

この特殊な場合では "value = dict.setdefault(key, getvalue(key))" も使
えますが、これは "getvalue()" 呼び出しが十分安価な場合に限ります。なぜ
ならそれが全ての場合に評価されるからです。


Python に switch や case 文がないのはなぜですか？
=================================================

一般に、構造化された switch 文は、式が特定の値または値の集合のいずれか
に一致するときに、一つのコードブロックを実行します。 Python 3.10 以降
では "match ... case" 文を使い、リテラル値や名前空間内の定数と簡単に照
合できます。 "match" 文について詳しくは、仕様 と チュートリアル を参照
してください。 以前から使える方法として、"if... elif... elif... else"
を並べる方法もあります。

非常に大きな数の選択肢から選ぶとき、値を呼び出す関数に対応づける辞書を
作れます。例えば:

   functions = {'a': function_1,
                'b': function_2,
                'c': self.method_1}

   func = functions[value]
   func()

オブジェクトのメソッドを呼び出すには、さらに単純に "getattr()" 組み込
み関数で特定の名前のメソッドを検索できます:

   class MyVisitor:
       def visit_a(self):
           ...

       def dispatch(self, value):
           method_name = 'visit_' + str(value)
           method = getattr(self, method_name)
           method()

メソッドの名前にこの例の "visit_" のような接頭辞を使うことを勧めます。
このような接頭辞がないと、信頼できないソースから値が与えられたときに、
オブジェクトの任意のメソッドを呼び出す攻撃をされる可能性があります。

C の switch-case-default のような、フォールスルーのある switch を模倣
することもできますが、はるかに難しいうえに必要性も少ないでしょう。


OS 特有のスレッド実装に依らずにインタプリタでスレッドをエミュレートすることはできないのですか？
===============================================================================================

答 1: 残念なことに、インタプリタは Python のスタックフレームごとに少な
くとも一つの C のスタックフレームを push します。同様に、拡張もほとん
どランダムなときに Python にコールバックすることがあります。よって、完
全なスレッド実装には C のスレッドサポートが必要です。

答 2: 幸運なことに、Stackless Python があります。これは完全に再デザイ
ンされたインタープリタで、Cのスタックを回避しています。


なぜラムダ式は文を含むことができないのですか?
=============================================

Python のラムダ式が文を含むことができないのは、Python の文法的な枠組み
が式の中にネストされた文を扱うことができないからです。しかし、Python
では、これは深刻な問題ではありません。他の言語のラムダに機能が追加され
ているのと違い、Python のラムダは単なる、関数を定義するのが面倒すぎる
場合のための簡略な記法に過ぎないのです。

関数は既に Python の第一級オブジェクトで、ローカルスコープ内で宣言でき
ます。従って、ローカルで定義された関数ではなくラムダを使う利点は、関数
の名前を考える必要が無いことだけです -- しかし、(ラムダ式が生み出すオ
ブジェクトと厳密に同じ型の) 関数オブジェクトが代入される先はただのロー
カル変数です！


Python を機械語、C、または他の言語にコンパイルできますか？
==========================================================

Cython は、 オプションアノテーションを付けた 修正バージョンの Python
から C 拡張 にコンパイルします。  Nuitka は Python から C++ コードへの
有望なコンパイラで、 フルセットの Python 言語サポートを目指しています
。


Python はメモリをどのように管理するのですか？
=============================================

Python のメモリ管理の詳細は実装に依ります。  Python の標準実装である
*CPython* は、参照カウントを使ってアクセスできない（訳注：参照されえな
い）オブジェクトを検出し、そして別の仕組みで参照サイクル（循環参照）を
集めます。サイクル検出アルゴリズムを定期的に実行し、アクセスできないサ
イクルを見つけて一連のオブジェクトを削除します。 "gc" モジュールは、ガ
ベージコレクションの実行、デバッグ統計の取得、コレクタのパラメータ調整
を行う関数を提供します。

ただし、他の実装（ Jython や PyPy など）では、本格的なガベージコレクタ
のような別の仕組みを用いているかもしれません。  この違いは微妙な移植の
問題を起こす可能性があります。もし あなたの Python コードが参照カウン
ト実装の振る舞いに依存している場合には。

Python の実装によっては、以下の (CPython では通る) コードはおそらく、
ファイルディスクリプタを使い果たすでしょう:

   for file in very_long_list_of_files:
       f = open(file)
       c = f.read(1)

実際、CPython の参照カウントとデストラクタのスキームを使えば "f" への
新しい代入ごとにファイルは閉じられます。しかし、伝統的な GC を使うと、
これらのファイルオブジェクトが回収され (て閉じられる) までに不定な、場
合によっては長い、間隔が空くことがあります。

Python の実装に依らずに動くコードを書くには、ファイルを明示的に閉じる
か、 "with" 文を使ってください。これでメモリ管理のスキームに関係なく動
きます:

   for file in very_long_list_of_files:
       with open(file) as f:
           c = f.read(1)


CPython はなぜ伝統的なガベージコレクションスキームを使わないのですか？
======================================================================

まず、それは C の標準的な機能ではないのでポータブルではありません。(確
かに Boehm GC ライブラリはあります。しかし、これにはアセンブリコードが
含まれ、*ほとんどの* 有名なプラットフォームに対応していますが全てでは
ありません。また、ほとんど透過的ですが、完全に透過的ではありません。
Python を対応させるにはパッチが必要です。)

伝統的な GC は Python が他のアプリケーションに組み込まれるときにも問題
となります。スタンドアロンの Python で動く限りでは、標準の "malloc()"
と "free()" を GC ライブラリから提供されるものに置き換えても問題ありま
せんが、Python を実装したアプリケーションは Python のものではない *独
自の* 代替品を使おうとするかもしれません。現在のようにすることで、
CPython は "malloc()" と "free()" が適切に実装されている限りどんなもの
にも対応させられます。


なぜ CPython の終了時にすべてのメモリが解放されるわけではないのですか？
=======================================================================

Python モジュールのグローバル名前空間から参照されているオブジェクトは
、Python の終了時に必ずしも解放されるとは限りません。 循環参照があると
、このようなことが起こる場合があります。 また、C ライブラリが割り当て
たメモリの一部には解放できないものもあります (例えば Purify のようなツ
ールはこれを報告します)。 それでも Python は終了時のメモリの後始末を積
極的に行い、すべてのオブジェクトを破棄しようとします。

解放時に特定のものを Python に確実に削除させたい場合は、"atexit" モジ
ュールを使い、それらを削除する関数を実行してください。


なぜタプルとリストという別のデータ型が用意されているのですか？
==============================================================

リストとタプルは、多くの点で似ていますが、一般には本質的に異なる方法で
使われます。タプルは、Pascal の "レコード" や C の　"構造体" と同様な
ものと考えられます。型が異なっても良い関連するデータの小さな集合で、グ
ループとして演算されます。例えば、デカルト座標は 2 つや 3 つの数のタプ
ルとして適切に表せます。

一方、リストは、もっと他の言語の配列に近いものです。全て同じ型の可変数
のオブジェクトを持ち、それらが一つ一つ演算される傾向にあります。例えば
、 "os.listdir('.')" はカレントディレクトリ内にあるファイルの文字列表
現のリストを返します。この出力を演算する関数は一般に、ディレクトリに一
つや二つの別のファイルを加えても壊れません。

タプルは *immutable* なので、一度タプルが生成されたら、そのどの要素も
新しい値に置き換えられません。  リストは *mutable* なので、リストの要
素はいつでも変更できます。   *hashable* な要素だけが辞書のキーとして使
えます。ほとんどの immutable 型は hashable のため、リストではなくタプ
ルがキーとして使えます。ただし注意点として、あるタプルが hashable とな
るのは、そのすべての要素が hashable である場合に限られます。


CPythonでリストはどのように実装されているのですか？
===================================================

CPython のリストは可変長配列で、Lispスタイルの連結リストではありません
。 この実装は他のオブジェクトへの参照の連続した配列を使用していて、こ
の配列へのポインタおよび配列長はリストの先頭の構造体に保存されています
。

これにより、リストのインデクシング "a[i]" は、リストの大きさやインデク
スの値に依存しないコストで演算できます。

要素が追加または挿入されるとき、この参照の配列は大きさが変更されます。
要素追加の繰り返しのパフォーマンスを上げるために、少し工夫されています
。配列が大きくなるとき、次の何回かは実際に大きさを変更する必要がないよ
うに、いくらかの追加の領域が割り当てられます。

リストの各種操作の計算コストについては、組み込み型の操作の時間計算量
を参照してください。


CPythonで辞書はどのように実装されていますか？
=============================================

CPython の辞書は大きさを変更できるハッシュテーブルとして実装されていま
す。B 木と比べて、ほとんどの条件下で (特に一般的な演算である) 探索のパ
フォーマンスが良いですし、実装も単純です。

辞書は、辞書に保存されているそれぞれのキーに対応するハッシュコードを
"hash()" ビルトイン関数で計算することで機能します。このハッシュコード
はキーやプロセスごとのシードによって大きく変化します。例えば、
"'Python'" のハッシュ値は "-539294296" ですが、ビットが一つ違うだけの
文字列 "'python'" のハッシュ値は "1142331976" です。そしてこのハッシュ
コードは、値が保存される内部配列での位置を計算するために使われます。保
存しているキーのハッシュ値が全て異なるとすれば、一定の時間 − Big-O 記
法では *O*(1) − でキーを検索できることになります。

辞書の各種操作の計算コストについては、組み込み型の操作の時間計算量 を
参照してください。


なぜ辞書のキーはイミュータブルでなくてはならないのですか？
==========================================================

辞書のハッシュテーブルの実装は、キーを見つけるために、キー値から計算さ
れたハッシュ値を使います。 もしキーがミュータブルなオブジェクトだった
ら、その値は変えられ、それによりハッシュ値も変わってしまいます。 しか
し、キーオブジェクトを変更したのが何者であれ、値が辞書のキーとして使わ
れていたと気付けないので、辞書の中のエントリを適切な場所に動かせません
。 そして、同じオブジェクトを探そうとしても、ハッシュ値が違うため見つ
かりません。 古い値を探そうとしても、そのハッシュ値に対応する格納場所
で見つかるオブジェクトの値は異なるでしょうから、これも見つかりません。

リストでインデクシングされた辞書が必要なら、まず単純にリストをタプルに
変換してください。関数 "tuple(L)" は、リスト "L" と同じエントリのタプ
ルを生成します。タプルはイミュータブルなので、辞書のキーとして使えます
。

いくつかの受け入れられなかった提案:

* リストのアドレス (オブジェクト ID) を使ってハッシュ値を計算する。 同
  じ値を持つ新しいリストを作っても見つからないため、この方法はうまくい
  きません。 例えば次のコードです。

     mydict = {[1, 2]: '12'}
     print(mydict[[1, 2]])

  "[1, 2]" の2行目のidは1行目のそれと異なってしまうために "KeyError"
  例外を送出するでしょう。言い換えれば、辞書のキーは "==" を使って比較
  されるべきであり、 "is" ではないということです。

* リストをキーとして使う際にコピーを作る。 リストはミュータブルなオブ
  ジェクトなので、自分自身への参照を含む場合があります。 その場合、コ
  ピーを行うコードが無限ループに陥るため、この方法はうまくいきません。

* リストをキーとして使うことを認めるが、ユーザにそれを変更させないよう
  に伝える。もしユーザが忘れたり、偶然にリストが変更されてしまったりし
  たら、追跡困難なバグの可能性を生じてしまいます。またこれは、
  "d.keys()" のすべての値は辞書のキーとして使えるという、辞書の重要な
  不変性も潰してしまいます。

* リストが一旦辞書のキーとして使われたら、読み出し専用のマークを付ける
  。問題は、値を変えられるのはトップレベルオブジェクトだけではないこと
  です。リストを含むタプルもキーとして使えます。全てを辞書のキーとして
  導入すると、そこから到達可能な全てのオブジェクトに読み出し専用のマー
  クを付ける必要があります -- そして再び、自己参照オブジェクトが無限ル
  ープを引き起こします。

必要ならばこれを回避する方法がありますが、自己責任のもとで行ってくださ
い。ミュータブルな構造を、 "__eq__()" と "__hash__()" メソッドの両方を
持つクラスインスタンスに含めることができます。その時、辞書 (またはハッ
シュに基づく別の構造体) に属するような全てのラッパーオブジェクトのハッ
シュ値が、そのオブジェクトが辞書 (その他の構造体) 中にある間固定され続
けることを確実にしてください。

   class ListWrapper:
       def __init__(self, the_list):
           self.the_list = the_list

       def __eq__(self, other):
           return self.the_list == other.the_list

       def __hash__(self):
           l = self.the_list
           result = 98767 - len(l)*555
           for i, el in enumerate(l):
               try:
                   result = result + (hash(el) % 9999999) * 1001 + i
               except Exception:
                   result = (result % 7777777) + i * 333
           return result

なお、リストのメンバーの中にハッシュ化できないものがある可能性や、算術
オーバーフローの可能性から、ハッシュ計算は複雑になります。

さらに、そのオブジェクトが辞書に含まれるか否かにかかわらず、 "o1 ==
o2" (すなわち "o1.__eq__(o2) is True") ならばいつでも "hash(o1) ==
hash(o2)" (すなわち "o1.__hash__() == o2.__hash__()") でなくてはなりま
せん。その制限に適合できなければ、辞書やその他のハッシュに基づく構造体
は間違いを起こします。

この "ListWrapper" の例では、異常を避けるため、ラッパオブジェクトが辞
書内にある限りラップされたリストが変更されてはなりません。この条件と満
たせなかった時の結果について知恵を絞る覚悟がない限り、これをしてはいけ
ません。よく考えてください。


なぜ list.sort() はソートされたリストを返さないのですか？
=========================================================

パフォーマンスが問題となる状況では、ソートするためだけにリストのコピー
を作るのは無駄が多いです。そこで、 "list.sort()" はインプレースにリス
トをソートします。このことを忘れないため、この関数はソートされたリスト
を返しません。こうすることで、ソートされたコピーが必要で、ソートされて
いないものも残しておきたいときに、うっかり上書きしてしまうようなことが
なくなります。

新しいリストを返したいなら、代わりに組み込みの "sorted()" 関数を使って
ください。この関数は、与えられたイテレート可能オブジェクトから新しいリ
ストを生成し、ソートして返します。例えば、辞書のキーをソートされた順序
でイテレートする方法は:

   for key in sorted(mydict):
       ...  # mydict[key] を使って何でもできる ...


Python ではインターフェース仕様をどのように定義し、遵守させるのですか？
=======================================================================

C++ や Java などの言語が提供するモジュールのインターフェース仕様は、そ
のモジュールのメソッドや関数のプロトタイプを記述します。 コンパイル時
にインターフェース仕様への適合を強制することが、大規模なプログラムの構
築に役立つと考える人は多くいます。

Python 2.6 で、抽象基底クラス (Abstract Base Class, ABC) が定義できる
ようになる "abc" モジュールが追加されました。なので "isinstance()" と
"issubclass()" を使って、インスタンスやクラスが、ある ABC を実装してい
るかどうかチェックできます。"collections.abc" モジュールでは、
"Iterable" 、 "Container" 、 "MutableMapping" などの便利な ABC が定義
されています。

Pythonでは、インターフェース仕様の多くの利点は、コンポーネントへの適切
なテスト規律により得られます。

モジュールのための適切なテストスイートは、回帰テストを提供し、モジュー
ルのインターフェース仕様や用例集としても役立ちます。多くの Python モジ
ュールは、簡単な「自己テスト」を提供するスクリプトとして実行できます。
複雑な外部インターフェースを使うモジュールさえ、外部インターフェースの
細かい「スタブ」エミュレーションで単独にテストできることが多いです。
"doctest" や "unittest" モジュール、あるいはサードパーティのテストフレ
ームワークで、モジュールのコードの全ての行に及ぶ徹底的なテストスイート
を構成できます。

Python で大きくて複雑なアプリケーションを構築するとき、インターフェー
ス仕様と同様に、適切なテスト規律も役立ちます。  実際には、インターフェ
ース仕様ではテストできないプログラムの属性もあるので、それ以上にもなり
えます。  例えば、 "list.append()" メソッドは新しい要素をある内部リス
トの終わりに加えます。インターフェース仕様ではこの "list.append()" の
実装が実際にこれを行うかをテストできませんが、テストスイートならこの機
能を簡単に確かめられます。

テストスイートを書くことはとても有用ですし、簡単にテストできるコード設
計を心がけると良いでしょう。人気を博している開発手法の一つ、テスト駆動
開発は、実際のコードを記述するよりも先に、まずテストスイートの部分を記
述するよう求めています。ご心配なく、Python は、あなたがいい加減でもテ
ストケースを全く書かなくても構いません。


なぜ goto が無いのですか？
==========================

1970年代、人々は気付きました。秩序なき goto は、理解するのも手直しする
のも困難という厄介な"スパゲッティ"コードに陥りがちであると。 高水準言
語では、分岐とループの手段があれば goto は不要です。 (Pythonだと、分岐
には "if" 文及び "or" ・ "and" ・ "if"/"else" 式を使います。ループには
"while" 文と "for" 文を使い、 ループ内に "continue" ・ "break" を含む
ことがあります)

関数の呼び出しをまたいでも動作する "構造化された goto" をまかなうもの
として例外を使えます。C、Fortran、その他の言語での "go" あるいは
"goto" 構造の適切な用途は全て、例外で同じようなことをすれば便利である
と、広く感じられています。例えば:

   class label(Exception): pass  # declare a label

   try:
       ...
       if condition: raise label()  # goto label
       ...
   except label:  # goto 移動先
       pass
   ...

例外ではループ内へ跳ぶことはできませんが、どちらにしてもそれは "goto"
の乱用と見なされるものです。使うのは控えてください。


なぜ raw 文字列 (r-strings) はバックスラッシュで終わってはいけないのですか？
============================================================================

正確には、奇数個のバックスラッシュで終わってはいけません。終わりの対に
なっていないバックスラッシュは、閉じ引用文字をエスケープし、終っていな
い文字列を残してしまいます。

raw 文字列は、独自にバックスラッシュの処理をしようとするプロセッサ (主
に正規表現エンジン) への入力を生成しやすいように設計されたものです。こ
のようなプロセッサは、終端の対になっていないバックスラッシュを結局エラ
ーとみなすので、raw 文字列はそれを認めません。その代わりに、バックスラ
ッシュでエスケープすることで、引用文字を文字列として渡すことができます
。r-string が意図された目的に使われるときに、この規則が役に立つのです
。

Windows のパス名を構築するときには、Windows のシステムコールは普通のス
ラッシュも受け付けることを憶えておいてください:

   f = open("/mydir/file.txt")  # 正常に動く！

DOS コマンドのパス名を構築するときには、例えばこの中のどれかを試してく
ださい:

   dir = r"\this\is\my\dos\dir" "\\"
   dir = r"\this\is\my\dos\dir\ "[:-1]
   dir = "\\this\\is\\my\\dos\\dir\\"


属性の代入に "with" 文が使えないのはなぜですか？
================================================

Python には、ブロックの実行を包む "with" 文があり、ブロックに入るとき
とブロックから出るときに、コードを呼び出します。以下のような構造を持つ
言語があります:

   with obj:
       a = 1               # これに相当： obj.a = 1
       total = total + 1   # obj.total = obj.total + 1

Python では、このような構造は曖昧になるでしょう。

Object Pascal、Delphi、C++のような他の言語では、静的な型を使うので、ど
のメンバに代入されているのかを曖昧さなく判断できます。 これが静的型付
けの要点です -- コンパイラは *いつでも* コンパイル時にすべての変数のス
コープを知るのです。

Python は動的な型を使います。実行時にどの属性が参照されるか事前に分か
りません。動作中にメンバ属性が追加あるいは除去されるかもしれません。こ
れでは、単純に読むだけではどのアトリビュートが参照されているか分かりま
せん。ローカルなのか、グローバルなのか、メンバ属性なのか？

例えば、以下の不完全なコード片を考えましょう:

   def foo(a):
       with a:
           print(x)

このコード片では、"a" は "x". というメンバ属性を持っていると仮定されて
います。しかし、Python ではインタプリタにはこの仮定を伝えられる仕組み
はありません。 "a" が、例えば整数だったら、どうなってしまうでしょうか
。 "x" という名前のグローバル変数があったら、それが "with" ブロックの
中で使われるのでしょうか。この通り、Python の動的な特質から、このよう
な選択はとても難しい物になっています。

しかし、"with" やそれに類する言語の機能の一番の利点 (コード量の削減)
は、 Python では代入により簡単に手に入れられます:

   function(args).mydict[index][index].a = 21
   function(args).mydict[index][index].b = 42
   function(args).mydict[index][index].c = 63

こう書いてください:

   ref = function(args).mydict[index][index]
   ref.a = 21
   ref.b = 42
   ref.c = 63

Python では実行時に名前束縛が解決され、後者はその解決が一度で済むため
、これには実行速度をあげる副作用もあります。

似た提案として、「先頭のドット」を使うなどして さらにコード量を減らす
構文は、明白さを優先して却下されました
(https://mail.python.org/pipermail/python-ideas/2016-May/040070.html
参照)。


なぜジェネレータは with 文をサポートしないのですか？
====================================================

技術的な理由で、ジェネレータは直接コンテキストマネージャとして使っても
うまく動きません。最も一般的なように、ジェネレータが最後まで回りきるイ
テレータとして使われる場合、クローズ処理は不要です。必要な場合は、
"with" 文で "contextlib.closing(generator)" のようにラップします。


if/while/def/class 文にコロンが必要なのはなぜですか？
=====================================================

主に可読性を高めるため (実験的な ABC 言語の結果の一つ) に、コロンが必
要です:

   if a == b
       print(a)

と:

   if a == b:
       print(a)

後者のほうが少し読みやすいことに注目してください。 この FAQ の回答でも
、原文ではコロンを使って例を区切っていることにも注目してください。 こ
れは英語では標準的な用法です。

他の小さな理由は、コロンによってエディタがシンタックスハイライトをしや
すくなることです。プログラムテキストの手の込んだ解析をしなくても、コロ
ンを探せばいつインデントを増やすべきかを決められます。


なぜ Python ではリストやタプルの最後にカンマがあっても良いのですか？
====================================================================

Python では、リスト、タプル、辞書の最後の要素の後端にカンマをつけても
良いことになっています:

   [1, 2, 3,]
   ('a', 'b', 'c',)
   d = {
       "A": [1, 5],
       "B": [6, 7],  # 最後のカンマはオプションだが良いスタイル
   }

これを許すのには、いくつかの理由があります。

リストやタプルや辞書のリテラルが複数行に渡っているときに、前の行にカン
マを追加するのを覚えておく必要が無いため、要素を追加するのが楽になりま
す。また、文法エラーを起こすこと無く、行の並べ替えを行うことができます
。

間違えてカンマを落としてしまうと、診断しづらいエラーにつながります。例
えば:

   x = [
     "fee",
     "fie"
     "foo",
     "fum"
   ]

このリストには4つの要素があるように見えますが、実際には3つしかありませ
ん。 "fee"、"fiefoo"、"fum" です。 常にカンマを付けるようにすれば、こ
の種のエラーが避けられます。

後端にカンマをつけても良いことにすれば、プログラムによるコード生成も簡
単になります。
