4. その他の制御フローツール
***************************

先ほど紹介した "while" 文の他にも、 Python は他の言語でおなじみの制御
フロー文を備えていますが、これらには多少ひねりを加えてあります。


4.1. "if" 文
============

おそらく最もおなじみの文型は "if" 文でしょう。例えば:

   >>> x = int(raw_input("Please enter an integer: "))
   Please enter an integer: 42
   >>> if x < 0:
   ...     x = 0
   ...     print 'Negative changed to zero'
   ... elif x == 0:
   ...     print 'Zero'
   ... elif x == 1:
   ...     print 'Single'
   ... else:
   ...     print 'More'
   ...
   More

ゼロ個以上の "elif" 部を使うことができ、 "else" 部を付けることもできま
す。キーワード '"elif"' は 'else if' を短くしたもので、過剰なインデン
トを避けるのに役立ちます。一連の "if" ... "elif" ... "elif" ...  は、
他の言語における "switch" 文や "case" 文の代用となります。


4.2. "for" 文
=============

Python の "for" 文は、読者が C 言語や Pascal 言語で使いなれているかも
しれない "for" 文とは少し違います。 (Pascal のように) 常に算術型の数列
にわたる反復を行ったり、 (C のように) 繰返しステップと停止条件を両方と
もユーザが定義できるようにするのとは違い、Python の "for" 文は、任意の
シーケンス型 (リストまたは文字列) にわたって反復を行います。反復の順番
はシーケンス中に要素が現れる順番です。例えば:

   >>> # Measure some strings:
   ... words = ['cat', 'window', 'defenestrate']
   >>> for w in words:
   ...     print w, len(w)
   ...
   cat 3
   window 6
   defenestrate 12

ループ内部でイテレートしているシーケンスを修正する必要があれば (例えば
選択されたアイテムを複製するために)、最初にコピーを作ることをお勧めし
ます。シーケンスに対するイテレーションは暗黙にコピーを作りません。スラ
イス記法はこれを特に便利にします:

   >>> for w in words[:]:  # Loop over a slice copy of the entire list.
   ...     if len(w) > 6:
   ...         words.insert(0, w)
   ...
   >>> words
   ['defenestrate', 'cat', 'window', 'defenestrate']


4.3. "range()" 関数
===================

数列にわたって反復を行う必要がある場合、組み込み関数 "range()"  が便利
です。この関数は算術型の数列を生成します:

   >>> range(10)
   [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

指定した終端値は生成されるシーケンスには入りません。 "range(10)" は 10
個の値を生成し、長さ 10 のシーケンスにおける各項目のインデクスとなりま
す。 range を別の数から開始したり、他の増加量 (負の増加量でさえも; 増
加量は時に 'ステップ(step)' と呼ばれることもあります) を指定することも
できます:

   >>> range(5, 10)
   [5, 6, 7, 8, 9]
   >>> range(0, 10, 3)
   [0, 3, 6, 9]
   >>> range(-10, -100, -30)
   [-10, -40, -70]

あるシーケンスにわたってインデクスで反復を行うには、 "range()" と
"len()" を次のように組み合わせられます:

   >>> a = ['Mary', 'had', 'a', 'little', 'lamb']
   >>> for i in range(len(a)):
   ...     print i, a[i]
   ...
   0 Mary
   1 had
   2 a
   3 little
   4 lamb

しかし、多くの場合は "enumerate()" 関数を使う方が便利です。 ループのテ
クニック を参照してください。


4.4. "break" 文と "continue" 文とループの "else" 節
===================================================

"break" 文は、C 言語と同じく、最も内側の "for" または "while" ループを
中断します。

ループ文は "else" 節を持つことができます。これは、 ("for" で) 反復処理
対象のリストを使い切ってループが終了したとき、または ("while" で) 条件
が偽になったときに実行されますが、 "break" 文でループが終了したときは
実行されません。この動作を、素数を探す下記のループを例にとって示します
:

   >>> for n in range(2, 10):
   ...     for x in range(2, n):
   ...         if n % x == 0:
   ...             print n, 'equals', x, '*', n/x
   ...             break
   ...     else:
   ...         # loop fell through without finding a factor
   ...         print n, 'is a prime number'
   ...
   2 is a prime number
   3 is a prime number
   4 equals 2 * 2
   5 is a prime number
   6 equals 2 * 3
   7 is a prime number
   8 equals 2 * 4
   9 equals 3 * 3

(そう、これは正しいコードです。よく見てください: "else" 節は "if" 文
**ではなく** 、 "for" ループに属しています。)

ループの "else" 句は、 "if" 文の "else" よりも "try" 文の "else" に似
ています。 "try" 文の "else" 句は例外が発生しなかった時に実行され、ル
ープの "else" 句は "break" されなかった場合に実行されます。 "try" 文と
例外についての詳細は 例外を処理する を参照してください。

"continue" 文も C 言語から借りてきたもので、ループの次のイテレーション
を実行します:

   >>> for num in range(2, 10):
   ...     if num % 2 == 0:
   ...         print "Found an even number", num
   ...         continue
   ...     print "Found a number", num
   Found an even number 2
   Found a number 3
   Found an even number 4
   Found a number 5
   Found an even number 6
   Found a number 7
   Found an even number 8
   Found a number 9


4.5. "pass" 文
==============

"pass" 文は何もしません。 "pass" は、文を書くことが構文上要求されてい
るが、プログラム上何の動作もする必要がない時に使われます:

   >>> while True:
   ...     pass  # Busy-wait for keyboard interrupt (Ctrl+C)
   ...

これは最小のクラスを作るときによく使われる方法です:

   >>> class MyEmptyClass:
   ...     pass
   ...

"pass" が使われるもう1つの場所は、新しいコードを書いている時の関数や条
件文の中身です。こうすることで、具体的なコードを書かないで抽象的なレベ
ルで考えることができます。 "pass" は何もすることなく無視されます:

   >>> def initlog(*args):
   ...     pass   # Remember to implement this!
   ...


4.6. 関数を定義する
===================

フィボナッチ数列 (Fibonacci series) を任意の上限値まで書き出すような関
数を作成できます:

   >>> def fib(n):    # write Fibonacci series up to n
   ...     """Print a Fibonacci series up to n."""
   ...     a, b = 0, 1
   ...     while a < n:
   ...         print a,
   ...         a, b = b, a+b
   ...
   >>> # Now call the function we just defined:
   ... fib(2000)
   0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597

"def" は関数の *定義 (definition)* を導くキーワードです。 "def" の後に
は、関数名と仮引数を丸括弧で囲んだリストを続けなければなりません。関数
の実体を構成する実行文は次の行から始め、インデントされていなければなり
ません。

関数の本体の記述する文の最初の行は文字列リテラルにすることもできます。
その場合、この文字列は関数のドキュメンテーション文字列 (documentation
string)、または *docstring* と呼ばれます。 (docstring については ドキ
ュメンテーション文字列 でさらに扱っています。) ドキュメンテーション文
字列を使ったツールには、オンライン文書や印刷文書を自動的に生成したり、
ユーザが対話的にコードから直接閲覧できるようにするものがあります。自分
が書くコードにドキュメンテーション文字列を入れるのはよい習慣です。書く
癖をつけてください。

関数を *実行 (execution)* するとき、関数のローカル変数のために使われる
新たなシンボルテーブル (symbol table) が用意されます。もっと正確にいう
と、関数内で変数への代入を行うと、その値はすべてこのローカルなシンボル
テーブルに記憶されます。一方、変数の参照を行うと、まずローカルなシンボ
ルテーブルが検索され、次にさらに外側の関数のローカルなシンボルテーブル
を検索し、その後グローバルなシンボルテーブルを調べ、最後に組み込みの名
前テーブルを調べます。従って、関数の中では、グローバルな変数を参照する
ことはできますが、直接値を代入することは ("global" 文で名前を挙げてお
かない限り)できません。

関数を呼び出す際の実際のパラメタ (引数) は、関数が呼び出されるときに関
数のローカルなシンボルテーブル内に取り込まれます。そうすることで、引数
は *値渡し (call by value)* で関数に渡されることになります (ここでの *
値 (value)* とは常にオブジェクトへの *参照(reference)* をいい、オブジ
ェクトの値そのものではありません) [1]。ある関数がほかの関数を呼び出す
ときには、新たな呼び出しのためにローカルなシンボルテーブルが新たに作成
されます。

関数の定義を行うと、関数名は現在のシンボルテーブル内に取り入れられます
。関数名の値は、インタプリタからはユーザ定義関数 (user-defined
function) として認識される型を持ちます。この値は別の名前に代入して、後
にその名前を関数として使うこともできます。これは一般的な名前変更のメカ
ニズムとして働きます:

   >>> fib
   <function fib at 10042ed0>
   >>> f = fib
   >>> f(100)
   0 1 1 2 3 5 8 13 21 34 55 89

他の言語出身の人からは、 "fib" は値を返さないので関数ではなく手続き
(procedure) だと異論があるかもしれませんね。技術的に言えば、実際には
"return" 文を持たない関数もややつまらない値ですが値を返しています。こ
の値は "None" と呼ばれます (これは組み込みの名前です)。 "None" だけを
書き出そうとすると、インタプリタは通常出力を抑制します。本当に出力した
いのなら、以下のように "print" を使うと見ることができます:

   >>> fib(0)
   >>> print fib(0)
   None

フィボナッチ数列の数からなるリストを出力する代わりに、値を返すような関
数を書くのは簡単です:

   >>> def fib2(n):  # return Fibonacci series up to n
   ...     """Return a list containing the Fibonacci series up to n."""
   ...     result = []
   ...     a, b = 0, 1
   ...     while a < n:
   ...         result.append(a)    # see below
   ...         a, b = b, a+b
   ...     return result
   ...
   >>> f100 = fib2(100)    # call it
   >>> f100                # write the result
   [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

この例は Python の新しい機能を示しています:

* "return" 文では、関数から一つ値を返します。 "return" の引数となる
  式 がない場合、 "None" が返ります。関数が終了したときにも "None" が
  返り ます。

* 文 "result.append(a)" では、リストオブジェクト "result" の *メソッ
  ド (method)* を呼び出しています。メソッドとは、オブジェクトに '属し
  てい る' 関数のことで、 "obj" を何らかのオブジェクト (式であっても構
  いま せん)、 "methodname" をそのオブジェクトで定義されているメソッド
  名と すると、 "obj.methodname" と書き表されます。異なる型は異なるメ
  ソッド を定義しています。異なる型のメソッドで同じ名前のメソッドを持
  つことが でき、あいまいさを生じることはありません。 (*クラス
  (class)* を使う ことで、自前のオブジェクト型とメソッドを定義すること
  もできます。 ク ラス 参照) 例で示されているメソッド "append()" は、
  リストオブジェク トで定義されています; このメソッドはリストの末尾に
  新たな要素を追加し ます。この例での "append()" は "result = result +
  [a]" と等価ですが 、より効率的です。


4.7. 関数定義についてもう少し
=============================

可変個の引数を伴う関数を定義することもできます。引数の定義方法には 3
つの形式があり、それらを組み合わせることができます。


4.7.1. デフォルトの引数値
-------------------------

もっとも便利なのは、一つ以上の引数に対してデフォルトの値を指定する形式
です。この形式を使うと、定義されている引数より少ない個数の引数で呼び出
せる関数を作成します:

   def ask_ok(prompt, retries=4, complaint='Yes or no, please!'):
       while True:
           ok = raw_input(prompt)
           if ok in ('y', 'ye', 'yes'):
               return True
           if ok in ('n', 'no', 'nop', 'nope'):
               return False
           retries = retries - 1
           if retries < 0:
               raise IOError('refusenik user')
           print complaint

この関数はいくつかの方法で呼び出せます:

* 必須の引数のみ与える: "ask_ok('Do you really want to quit?')"

* 一つのオプション引数を与える: "ask_ok('OK to overwrite the file?',
  2)"

* 全ての引数を与える: "ask_ok('OK to overwrite the file?', 2, 'Come
  on, only yes or no!')"

この例では "in" キーワードが導入されています。このキーワードはシーケン
スが特定の値を含んでいるかどうか調べるのに使われます。

デフォルト値は、関数が定義された時点で、関数を *定義している* 側のスコ
ープ (scope) で評価されるので

   i = 5

   def f(arg=i):
       print arg

   i = 6
   f()

は "5" を出力します。

**重要な警告:**  デフォルト値は 1 度だけしか評価されません。デフォルト
値がリストや辞書のような変更可能なオブジェクトの時にはその影響がでます
。例えば以下の関数は、後に続く関数呼び出しで関数に渡されている引数を累
積します:

   def f(a, L=[]):
       L.append(a)
       return L

   print f(1)
   print f(2)
   print f(3)

このコードは、以下を出力します

   [1]
   [1, 2]
   [1, 2, 3]

後続の関数呼び出しでデフォルト値を共有したくなければ、代わりに以下のよ
うに関数を書くことができます:

   def f(a, L=None):
       if L is None:
           L = []
       L.append(a)
       return L


4.7.2. キーワード引数
---------------------

関数を "kwarg=value" という形式の *キーワード引数* を使って呼び出すこ
ともできます。例えば、以下の関数:

   def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue'):
       print "-- This parrot wouldn't", action,
       print "if you put", voltage, "volts through it."
       print "-- Lovely plumage, the", type
       print "-- It's", state, "!"

は、必須引数 ("voltage") とオプション引数 ("state"、"action"、"type")
を受け付けます。この関数は以下のいずれかの方法で呼び出せます:

   parrot(1000)                                          # 1 positional argument
   parrot(voltage=1000)                                  # 1 keyword argument
   parrot(voltage=1000000, action='VOOOOOM')             # 2 keyword arguments
   parrot(action='VOOOOOM', voltage=1000000)             # 2 keyword arguments
   parrot('a million', 'bereft of life', 'jump')         # 3 positional arguments
   parrot('a thousand', state='pushing up the daisies')  # 1 positional, 1 keyword

が、以下の呼び出しは不適切です:

   parrot()                     # required argument missing
   parrot(voltage=5.0, 'dead')  # non-keyword argument after a keyword argument
   parrot(110, voltage=220)     # duplicate value for the same argument
   parrot(actor='John Cleese')  # unknown keyword argument

関数の呼び出しにおいて、キーワード引数は位置指定引数の後でなければなり
ません。渡されるキーワード引数は全て、関数で受け付けられる引数のいずれ
かに対応していなければならず (例えば、"actor" はこの "parrot" 関数の引
数として適切ではありません)、順序は重要ではありません。これはオプショ
ンでない引数でも同様です (例えば、"parrot(voltage=1000)" も適切です)。
いかなる引数も値を複数回は受け取れません。この制限により失敗する例は:

   >>> def function(a):
   ...     pass
   ...
   >>> function(0, a=0)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: function() got multiple values for keyword argument 'a'

仮引数の最後に "**name" の形式のものがあると、それまでの仮引数に対応し
たものを除くすべてのキーワード引数が入った辞書 (マッピング型 --- dict
を参照) を受け取ります。 "**name" は "*name" の形式をとる、仮引数のリ
ストを超えた位置指定引数の入ったタプルを受け取る引数 (次の節で述べます
) と組み合わせることができます。 ("*name" は "**name" より前になければ
なりません)。例えば、ある関数の定義を以下のようにすると:

   def cheeseshop(kind, *arguments, **keywords):
       print "-- Do you have any", kind, "?"
       print "-- I'm sorry, we're all out of", kind
       for arg in arguments:
           print arg
       print "-" * 40
       keys = sorted(keywords.keys())
       for kw in keys:
           print kw, ":", keywords[kw]

呼び出しは以下のようになり:

   cheeseshop("Limburger", "It's very runny, sir.",
              "It's really very, VERY runny, sir.",
              shopkeeper='Michael Palin',
              client="John Cleese",
              sketch="Cheese Shop Sketch")

もちろん以下のように出力されます:

   -- Do you have any Limburger ?
   -- I'm sorry, we're all out of Limburger
   It's very runny, sir.
   It's really very, VERY runny, sir.
   ----------------------------------------
   client : John Cleese
   shopkeeper : Michael Palin
   sketch : Cheese Shop Sketch

キーワード引数名のリストを、キーワード辞書の "keys()" メソッドの結果を
ソートして作成していることに注目してください。"sort()" が呼び出されて
いないと、引数が出力される順番は不確定となります。


4.7.3. 任意引数リスト
---------------------

最後に、最も使うことの少ない選択肢として、関数が任意の個数の引数で呼び
出せるよう指定する方法があります。これらの引数はタプル (タプルとシーケ
ンス を参照) に格納されます。可変個の引数の前に、ゼロ個かそれ以上の引
数があっても構いません。

   def write_multiple_items(file, separator, *args):
       file.write(separator.join(args))


4.7.4. 引数リストのアンパック
-----------------------------

引数がすでにリストやタプルになっていて、個別な固定引数を要求する関数呼
び出しに渡すためにアンパックする必要がある場合には、逆の状況が起こりま
す。例えば、組み込み関数 "range()" は引数 *start* と *stop* を別に与え
る必要があります。個別に引数を与えることができない場合、関数呼び出しを
"*" 演算子を使って書き、リストやタプルから引数をアンパックします:

   >>> range(3, 6)             # normal call with separate arguments
   [3, 4, 5]
   >>> args = [3, 6]
   >>> range(*args)            # call with arguments unpacked from a list
   [3, 4, 5]

同じやりかたで、"**" オペレータを使って辞書でもキーワード引数を渡すこ
とができます:

   >>> def parrot(voltage, state='a stiff', action='voom'):
   ...     print "-- This parrot wouldn't", action,
   ...     print "if you put", voltage, "volts through it.",
   ...     print "E's", state, "!"
   ...
   >>> d = {"voltage": "four million", "state": "bleedin' demised", "action": "VOOM"}
   >>> parrot(**d)
   -- This parrot wouldn't VOOM if you put four million volts through it. E's bleedin' demised !


4.7.5. ラムダ式
---------------

キーワード "lambda" を使うと、名前のない小さな関数を生成できます。例え
ば "lambda a, b: a+b" は、二つの引数の和を返す関数です。ラムダ式の関数
は、関数オブジェクトが要求されている場所にならどこでも使うことができま
す。ラムダ式は、構文上単一の式に制限されています。意味付け的には、ラム
ダ形式は単に通常の関数定義に構文的な糖衣をかぶせたものに過ぎません。入
れ子構造になった関数定義と同様、ラムダ式もそれを取り囲むスコープから変
数を参照することができます:

   >>> def make_incrementor(n):
   ...     return lambda x: x + n
   ...
   >>> f = make_incrementor(42)
   >>> f(0)
   42
   >>> f(1)
   43

上記の例は、関数を返すところでラムダ式を使っています。もう1つの例では
、ちょっとした関数を引数として渡すのに使っています:

   >>> pairs = [(1, 'one'), (2, 'two'), (3, 'three'), (4, 'four')]
   >>> pairs.sort(key=lambda pair: pair[1])
   >>> pairs
   [(4, 'four'), (1, 'one'), (3, 'three'), (2, 'two')]


4.7.6. ドキュメンテーション文字列
---------------------------------

ドキュメンテーション文字列については、その内容と書式に関する慣習をいく
つか挙げます。

最初の行は、常に対象物の目的を短く簡潔にまとめたものでなくてはなりませ
ん。簡潔に書くために、対象物の名前や型を明示する必要はありません。名前
や型は他の方法でも得られるからです (名前がたまたま関数の演算内容を記述
する動詞である場合は例外です)。最初の行は大文字で始まり、ピリオドで終
わっていなければなりません。

ドキュメンテーション文字列中にさらに記述すべき行がある場合、二行目は空
行にし、まとめの行と残りの記述部分を視覚的に分離します。つづく行は一つ
またはそれ以上の段落で、対象物の呼び出し規約や副作用について記述します
。

Python のパーザは複数行にわたる Python 文字列リテラルからインデントを
剥ぎ取らないので、ドキュメントを処理するツールでは必要に応じてインデン
トを剥ぎ取らなければなりません。この処理は以下の規約に従って行います。
最初の行の *後にある* 空行でない最初の行が、ドキュメント全体のインデン
トの量を決めます。(最初の行は通常、文字列を開始するクオートに隣り合っ
ているので、インデントが文字列リテラル中に現れないためです。) このイン
デント量と "等価な" 空白が、文字列のすべての行頭から剥ぎ取られます。イ
ンデントの量が少ない行を書いてはならないのですが、もしそういう行がある
と、先頭の空白すべてが剥ぎ取られます。インデントの空白の大きさが等しい
かどうかは、タブ文字を (通常は 8 文字のスペースとして) 展開した後に調
べられます。

以下に複数行のドキュメンテーション文字列の例を示します:

   >>> def my_function():
   ...     """Do nothing, but document it.
   ...
   ...     No, really, it doesn't do anything.
   ...     """
   ...     pass
   ...
   >>> print my_function.__doc__
   Do nothing, but document it.

       No, really, it doesn't do anything.


4.8. 間奏曲: コーディングスタイル
=================================

これからより長くより複雑な Python のコードを書いていくので、そろそろ *
コーディングスタイル* について語っても良い頃です。ほとんどの言語は様々
なスタイルで書け (もっと簡潔に言えば *フォーマットでき*)、スタイルによ
って読み易さが異なります。他人にとって読み易いコードにしようとするのは
どんなときでも良い考えであり、良いコーディングスタイルを採用することが
非常に強力な助けになります。

Python には、ほとんどのプロジェクトが守っているスタイルガイドとして
**PEP 8** があります。それは非常に読み易く目に優しいコーディングスタイ
ルを推奨しています。全ての Python 開発者はある時点でそれを読むべきです
。ここに最も重要な点を抜き出しておきます:

* インデントには空白 4 つを使い、タブは使わないこと。

  空白 4 つは (深くネストできる) 小さいインデントと (読み易い) 大きい
  インデントのちょうど中間に当たります。タブは混乱させるので、使わずに
  おくのが良いです。

* ソースコードの幅が 79 文字を越えないように行を折り返すこと。

  こうすることで小さいディスプレイを使っているユーザも読み易くなり、大
  きなディスプレイではソースコードファイルを並べることもできるようにな
  ります。

* 関数やクラスや関数内の大きめのコードブロックの区切りに空行を使いな
  さ い。

* 可能なら、コメントは行に独立で書きなさい

* docstring を使いなさい。

* 演算子の前後とコンマの後には空白を入れ、括弧類のすぐ内側には空白を
  入 れないこと: "a = f(1, 2) + g(3, 4)"。

* クラスや関数に一貫性のある名前を付けなさい。慣習では "CamelCase"
  を クラス名に使い、 "lower_case_with_underscores" を関数名やメソッド
  名 に使います。常に "self" をメソッドの第 1 引数の名前 (クラスやメソ
  ッ ドについては クラス初見 を見よ) として使いなさい。

* あなたのコードを世界中で使ってもらうつもりなら、風変りなエンコーデ
  ィ ングは使わないこと。どんな場合でも、プレーン ASCII が最も上手くい
  き ます。

-[ 注記 ]-

[1] 実際には、*オブジェクトへの参照渡し (call by object
    reference)* と 書けばよいのかもしれません。というのは、変更可能な
    オブジェクトが渡 されると、関数の呼び出し側は、呼び出された側の関
    数がオブジェクトに (リストに値が挿入されるといった) 何らかの変更に
    出くわすことになる からです。
