デザインと歴史 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 のような多くの一般的な言語と同じように振る舞います。

Many numbers that can be written easily in decimal notation cannot be
expressed exactly in binary floating point.  For example, after:

   >>> x = 1.2

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

   1.0011001100110011001100110011001100110011001100110011 (binary)

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

   1.1999999999999999555910790149937383830547332763671875 (decimal)

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

For a fuller explanation, please see the floating-point arithmetic
chapter in the Python tutorial.


なぜ 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" と書かなければならないので、メソッドの中の self
が付いていない名前への参照は、そのインスタンスのディレクトリを検索する
までもなくローカル変数とわかります。別の言い方をすれば、ローカル変数と
インスタンス変数は二つの異なる名前空間に存在し、Python にどちらの名前
空間を使うかを伝えなくてはならないのです。


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

Python 3.8 以降ならできるよ!

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

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

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


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

Guidoいわく：

   (a) For some operations, prefix notation just reads better than
   postfix -- prefix (and infix!) operations have a long tradition in
   mathematics which likes notations where the visuals help the
   mathematician thinking about a problem. Compare the easy with which
   we rewrite a formula like x*(a+b) into x*a + x*b to the clumsiness
   of doing the same thing using a raw OO notation.

   (b) When I read code that says len(x) I *know* that it is asking
   for the length of something. This tells me two things: the result
   is an integer, and the argument is some kind of container. To the
   contrary, when I read x.len(), I have to already know that x is
   some kind of container implementing an interface or inheriting from
   a class that has a standard len(). Witness the confusion we
   occasionally have when a class that is not implementing a mapping
   has a get() or keys() method, or something that isn't a file has a
   write() method.

   -- 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" 文で簡単にマッチさせることが
できます。より古い手段は一連の "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 compiles a modified version of Python with optional annotations
into C extensions.  Nuitka is an up-and-coming compiler of Python into
C++ code, aiming to support the full Python language.


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

Python のメモリ管理の詳細は実装に依ります。Python の標準の C 実装
*CPython* は参照カウントを使って、アクセスできないオブジェクトを探しま
す。また別のメカニズムを使って参照サイクルを集めます。これはサイクル検
出アルゴリズムを定期的に実行し、アクセスできないサイクルを探し、巻き込
まれたオブジェクトを削除します。 "gc" モジュールの関数で、ガベージコレ
クションを実行し、デバッグ統計を取得し、コレクタのパラメタを変更できま
す。

Other implementations (such as Jython or PyPy), however, can rely on a
different mechanism such as a full-blown garbage collector.  This
difference can cause some subtle porting problems if your Python code
depends on the behavior of the reference counting implementation.

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('.')" はカレントディレクトリ内にあるファイルの文字列表
現のリストを返します。この出力を演算する関数は一般に、ディレクトリに一
つや二つの別のファイルを加えても壊れません。

タプルはイミュータブルなので、一度タプルが生成されたら、そのどの要素も
新しい値に置き換えられません。リストはミュータブルなので、リストの要素
はいつでも変更できます。イミュータブルな要素だけが辞書のキーとして使え
るので、リストではなくタプルだけがキーとして使えます。


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):
       ...  # do whatever with 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" モジュール、あるいはサードパーティのテストフレ
ームワークで、モジュールのコードの全ての行に及ぶ徹底的なテストスイート
を構成できます。

An appropriate testing discipline can help build large complex
applications in Python as well as having interface specifications
would.  In fact, it can be better because an interface specification
cannot test certain properties of a program.  For example, the
"list.append()" method is expected to add new elements to the end of
some internal list; an interface specification cannot test that your
"list.append()" implementation will actually do this correctly, but
it's trivial to check this property in a test suite.

テストスイートを書くことはとても有用ですし、簡単にテストできるコード設
計を心がけると良いでしょう。人気を博している開発手法の一つ、テスト駆動
開発は、実際のコードを記述するよりも先に、まずテストスイートの部分を記
述するよう求めています。ご心配なく、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:  # where to goto
       pass
   ...

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


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

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

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

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

   f = open("/mydir/file.txt")  # works fine!

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               # equivalent to 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],  # last trailing comma is optional but good style
   }

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

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

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

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

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

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