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

前章で紹介した "while" 文の他にも、 Python にはいくつか制御フローツー
ルがあり、本章で説明します。


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

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

   >>> x = int(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" 文の代用となります。

いくつかの定数と同じ値かを比較する場合や、特定の型や属性かを確認する場
合には、"match" 文が便利です。詳細は match 文 を参照してください。


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

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

   >>> # 文字列の長さを計測:
   >>> words = ['cat', 'window', 'defenestrate']
   >>> for w in words:
   ...     print(w, len(w))
   ...
   cat 3
   window 6
   defenestrate 12

コレクションオブジェクトの値を反復処理をしているときに、そのコレクショ
ンオブジェクトを変更するコードは理解するのが面倒になり得ます。 そうす
るよりも、コレクションオブジェクトのコピーに対して反復処理をするか、新
しいコレクションオブジェクトを作成する方が通常は理解しやすいです:

   # コレクション作成
   users = {'Hans': 'active', 'Éléonore': 'inactive', '景太郎': 'active'}

   # 方針:  コピーを反復
   for user, status in users.copy().items():
       if status == 'inactive':
           del users[user]

   # 方針:  新コレクション作成
   active_users = {}
   for user, status in users.items():
       if status == 'active':
           active_users[user] = status


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

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

   >>> for i in range(5):
   ...     print(i)
   ...
   0
   1
   2
   3
   4

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

   >>> list(range(5, 10))
   [5, 6, 7, 8, 9]

   >>> list(range(0, 10, 3))
   [0, 3, 6, 9]

   >>> list(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()" 関数を使う方が便利です。 ループのテ
クニック を参照してください。

range を直接出力すると変なことになります:

   >>> range(10)
   range(0, 10)

"range()" が返すオブジェクトは、いろいろな点でリストであるかのように振
る舞いますが、本当はリストではありません。これは、イテレートした時に望
んだ数列の連続した要素を返すオブジェクトです。しかし実際にリストを作る
わけではないので、スペースの節約になります。

このようなオブジェクトは *イテラブル* と呼ばれます。 これらは関数や構
成物のターゲットとして、あるだけの項目を逐次与えるのに適しています。
"for" 文がそのような構成物であることはすでに見てきており、イテラブルを
受け取る関数の例には "sum()" があります:

   >>> sum(range(4))  # 0 + 1 + 2 + 3
   6

この後には、イテラブルを返したりイテラブルを引数で受け取るいくつかの関
数が出てきます。 データ構造 では、 "list()" についてより詳しく説明しま
す。


4.4. "break" 文と "continue" 文
===============================

"break" 文は、その *break* 文を内包している最も内側にある "for" 文また
は "while" 文から抜け出すことができます:

   >>> for n in range(2, 10):
   ...     for x in range(2, n):
   ...         if n % x == 0:
   ...             print(f"{n} は {x} * {n//x} と等しい")
   ...             break
   ...
   4 は 2 * 2 と等しい
   6 は 2 * 3 と等しい
   8 は 2 * 4 と等しい
   9 は 3 * 3 と等しい

"continue" 文はループの次のイテレーションを実行します:

   >>> for num in range(2, 10):
   ...     if num % 2 == 0:
   ...         print(f"偶数 {num} を見つけた")
   ...         continue
   ...     print(f"奇数 {num} を見つけた")
   ...
   偶数 2 を見つけた
   奇数 3 を見つけた
   偶数 4 を見つけた
   奇数 5 を見つけた
   偶数 6 を見つけた
   奇数 7 を見つけた
   偶数 8 を見つけた
   奇数 9 を見つけた


4.5. ループの "else" 節
=======================

"for" または "while" ループ中の "break" 文は "else" 節と対になる場合が
あります。"break" を実行せずにループが終了すると、"else" 節が実行され
ます。

"for" 文の場合、 "else" 節はループ処理の最後のイテレーションが実行され
たあと、つまりbreakが発生しなかった場合に実行されます。

"while" 文の場合は、ループ条件が偽となったあとに実行されます。

どちらのループでも、ループが "break" によって終了した場合は "else" 句
は **実行されません**。当然、 "return" や例外の発生によってループが途
中で終了した場合にも、"else" 節の実行はスキップされます。

その例として、素数を探索する "for" 文を以下に示します:

   >>> for n in range(2, 10):
   ...     for x in range(2, n):
   ...         if n % x == 0:
   ...             print(n, 'は', x, '*', n//x, 'と等しい')
   ...             break
   ...     else:
   ...         # 因数が見つからないとループは最後まで実行される
   ...         print(n, 'は素数です')
   ...
   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" ループに属しています。)

One way to think of the else clause is to imagine it paired with the
"if" inside the loop.  As the loop executes, it will run a sequence
like if/if/if/else. The "if" is inside the loop, encountered a number
of times. If the condition is ever true, a "break" will happen. If the
condition is never true, the "else" clause outside the loop will
execute.

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


4.6. "pass" 文
==============

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

   >>> while True:
   ...     pass  # キーボード割り込み(Ctrl+C)のためのビジーウェイト
   ...

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

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

"pass" のもう 1 つの使い道は、新しいコードを書いているときの関数や条件
文の仮置きの本体としてです。こうすることで、より抽象的なレベルで考え続
けられます。 "pass" は何事も無く無視されます

   >>> def initlog(*args):
   ...     pass   # ここを忘れずに実装すること!
   ...

For this last case, many people use the ellipsis literal "..." instead
of "pass". This use has no special meaning to Python, and is not part
of the language definition (you could use any constant expression
here), but "..." is used conventionally as a placeholder body as well.
See Ellipsis オブジェクト.


4.7. "match" 文
===============

A "match" statement takes an expression and compares its value to
successive patterns given as one or more case blocks.  This is
superficially similar to a switch statement in C, Java or JavaScript
(and many other languages), but it's more similar to pattern matching
in languages like Rust or Haskell. Only the first pattern that matches
gets executed and it can also extract components (sequence elements or
object attributes) from the value into variables. If no case matches,
none of the branches is executed.

最も単純な形式は、対象の値に対して1つ以上のリテラルです:

   def http_error(status):
       match status:
           case 400:
               return "Bad request"
           case 404:
               return "Not found"
           case 418:
               return "I'm a teapot"
           case _:
               return "Something's wrong with the internet"

Note the last block: the "variable name" "_" acts as a *wildcard* and
never fails to match.

複数のリテラルを "|" ("or")を使用して組み合わせて1つのパターンにできま
す:

   case 401 | 403 | 404:
       return "Not allowed"

パターンはアンパック代入ができ、変数に結びつけられます:

   # point(座標) は (x, y) のタプル
   match point:
       case (0, 0):
           print("原点")
       case (0, y):
           print(f"Y={y}")
       case (x, 0):
           print(f"X={x}")
       case (x, y):
           print(f"X={x}, Y={y}")
       case _:
           raise ValueError("座標ではない")

このコードは注意して見てください！ 最初のパターンには2つのリテラルがあ
り、上で示したリテラルパターンの拡張と考えることができます。 しかし次
の2つのパターンはリテラルと変数の組み合わせのため、対象("point")から値
を取り出して変数に *結びつけ* ます。 4番目のパターンは2つの値を取り込
みます。 これは、アンパック代入 "(x, y) = point" と概念的に似ています
。

データを構造化するためにクラスを使っている場合は、クラス名の後ろにコン
ストラクターのように引数のリストを指定できます。属性の値は変数に取り込
まれます。

   class Point:
       def __init__(self, x, y):
           self.x = x
           self.y = y

   def where_is(point):
       match point:
           case Point(x=0, y=0):
               print("原点")
           case Point(x=0, y=y):
               print(f"Y={y}")
           case Point(x=x, y=0):
               print(f"X={x}")
           case Point():
               print("それ以外のどこか")
           case _:
               print("座標ではない")

いくつかの組み込みクラスでは位置引数が使用でき、属性の順番を提供します
(例: データクラス)。クラスの "__match_args__" 特殊属性によって、パター
ンの中で属性の明確な位置を定義することもできます。("x", "y")が設定され
た場合、以下のすべてのパターンは等価です(すべて属性 "y" が "var" 変数
に結びつけられます):

   Point(1, var)
   Point(1, y=var)
   Point(x=1, y=var)
   Point(y=var, x=1)

おすすめのパターンの読み方は、パターンが、代入文の左辺に配置するものを
拡張した形式であるとみなすことです。 これにより、どの変数になにが代入
されるかが分かります。 単独の名前（上記の "var" など）だけがマッチ文で
値が代入されます。ドット付きの名前（"foo.bar" など）、属性名（上記の
"x="、"y=" など ）、クラス名（名前の後ろの "(...)"  によって判別される
。上記の "Point" など）には値は代入されません。

パターンはいくらでも入れ子 (ネスト) にすることができます。例えば、
"__match_args__" を追加した Point クラスのリストに対して次のようにマッ
チを行うことができます:

   class Point:
       __match_args__ = ('x', 'y')
       def __init__(self, x, y):
           self.x = x
           self.y = y

   match points:
       case []:
           print("座標が存在しない")
       case [Point(0, 0)]:
           print("原点")
       case [Point(x, y)]:
           print(f"1つの座標 {x}, {y}")
       case [Point(0, y1), Point(0, y2)]:
           print(f"Y軸の {y1}, {y2} に2つの座標")
       case _:
           print("それ以外のどこか")

パターンに "if" 節を追加できます。これは "ガード" と呼ばれます。ガード
がfalseの場合、"match" は次のcaseブロックの処理に移動します。ガードを
評価する前に値が取り込まれることに注意してください:

   match point:
       case Point(x, y) if x == y:
           print(f"Y=X at {x}")
       case Point(x, y):
           print(f"対角線上ではない")

この文のその他のいくつか重要な特徴:

* アンパック代入のように、タプルとリストのパターンでは正確に同じ意味で
  、任意のシーケンスと一致します。重要な例外として、イテレーターや文字
  列ではマッチしません。

* シーケンスパターンは拡張アンパックをサポート: "[x, y, *rest]" と
  "(x, y, *rest)" はアンパック代入として同じように動作します。"*" のあ
  との変数名は "_" でもよく、そのため "(x, y, *_)" は最低でも2つのアイ
  テムを持つシーケンスにマッチし、残りのアイテムは変数に結びつけられま
  せん。

* マッピングパターン: "{"bandwidth": b, "latency": l}" は辞書から
  ""bandwidth"" と ""latency"" の値を取り込みます。シーケンスパターン
  とは異なり、それ以外のキーは無視されます。アンパッキングのような
  "**rest" もサポートされています（しかし、 "**_" は冗長なため禁止され
  ています）。

* サブパターンでは "as" キーワードを使用して値を取り込みます:

     case (Point(x1, y1), Point(x2, y2) as p2): ...

  この例では入力から2番目の要素を "p2" として取り込みます（入力が2つの
  ポイントのシーケンスである場合）

* ほとんどのリテラルは同一性を比較しますが、シングルトンの "True"、
  "False"、"None" では識別値を比較します。

* パターンには名前を付けた定数が使用できます。値を取り込む変数としてと
  解釈することを防ぐために、ドット付きの変数名にする必要があります。

     from enum import Enum
     class Color(Enum):
         RED = 'red'
         GREEN = 'green'
         BLUE = 'blue'

     color = Color(input("Enter your choice of 'red', 'blue' or 'green': "))

     match color:
         case Color.RED:
             print("I see red!")
         case Color.GREEN:
             print("Grass is green")
         case Color.BLUE:
             print("I'm feeling the blues :(")

より詳細な説明と追加の例は **PEP 636** にチュートリアル形式で記述して
あります。


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

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

   >>> def fib(n):    # nまでのフィボナッチ数を出力する
   ...     """nまでのフィボナッチ数をprintする。"""
   ...     a, b = 0, 1
   ...     while a < n:
   ...         print(a, end=' ')
   ...         a, b = b, a+b
   ...     print()
   ...
   >>> # 定義した関数を呼び出す:
   >>> 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" 文で指定されていたり、外側の関数の変数が "nonlocal" 文で指定
されていない限り) グローバル変数や外側の関数の変数に直接値を代入できま
せんが、参照することはできます。

関数を呼び出す際の実際の引数 (実引数) は、関数が呼び出されるときに関数
のローカルなシンボルテーブル内に取り込まれます。そうすることで、実引数
は *値渡し (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):  # nまでのフィボナッチ数を返す
   ...     """nまでのフィボナッチ数を含むリストを返す。"""
   ...     result = []
   ...     a, b = 0, 1
   ...     while a < n:
   ...         result.append(a)    # 以下参照
   ...         a, b = b, a+b
   ...     return result
   ...
   >>> f100 = fib2(100)    # 関数を呼び出す
   >>> f100                # 結果を出力する
   [0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

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

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

* The statement "result.append(a)" calls a *method* of the list object
  "result".  A method is a function that 'belongs' to an object and is
  named "obj.methodname", where "obj" is some object (this may be an
  expression), and "methodname" is the name of a method that is
  defined by the object's type. Different types define different
  methods.  Methods of different types may have the same name without
  causing ambiguity.  (It is possible to define your own object types
  and methods, using *classes*, see クラス) The method "append()"
  shown in the example is defined for list objects; it adds a new
  element at the end of the list.  In this example it is equivalent to
  "result = result + [a]", but more efficient.


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

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


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

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

   def ask_ok(prompt, retries=4, reminder='再試行してください!'):
       while True:
           reply = input(prompt)
           if reply in {'y', 'ye', 'yes'}:
               return True
           if reply in {'n', 'no', 'nop', 'nope'}:
               return False
           retries = retries - 1
           if retries < 0:
               raise ValueError('無効なユーザーの入力')
           print(reminder)

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

* 必須の引数のみ与える: "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.9.2. キーワード引数
---------------------

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

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

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

   parrot(1000)                                          # 1つの位置引数
   parrot(voltage=1000)                                  # 1つのキーワード引数
   parrot(voltage=1000000, action='VOOOOOM')             # 2つのキーワード引数
   parrot(action='VOOOOOM', voltage=1000000)             # 2つのキーワード引数
   parrot('a million', 'bereft of life', 'jump')         # 3つの位置引数
   parrot('a thousand', state='pushing up the daisies')  # 1との位置引数と1つのキーワード引数

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

   parrot()                     # 必須の引数がない
   parrot(voltage=5.0, 'dead')  # キーワード引数の後ろにキーワードのない引数
   parrot(110, voltage=220)     # 同じ引数に対して2つの値を指定
   parrot(actor='John Cleese')  # 未知のキーワード引数

関数の呼び出しにおいて、キーワード引数は位置引数の後でなければなりませ
ん。渡されるキーワード引数は全て、関数で受け付けられる引数のいずれかに
対応していなければならず (例えば、"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 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)
       for kw in keywords:
           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.
   ----------------------------------------
   shopkeeper : Michael Palin
   client : John Cleese
   sketch : Cheese Shop Sketch

なお、複数のキーワード引数を与えた場合に、それらが出力される順序は、関
数呼び出しで与えられた順序と同じになります。


4.9.3. 特殊なパラメータ
-----------------------

デフォルトでは、引数は位置またはキーワードによる明示で Python 関数に渡
されます。 可読性とパフォーマンスのために、その引数が位置、位置または
キーワード、キーワードのどれで渡されるかを開発者が判定するのに関数定義
だけを見ればよいように、引数の渡され方を制限することには意味があります
。

関数定義は次のようになります:

   def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
         -----------    ----------     ----------
           |             |                  |
           |        位置またはキーワード    |
           |                                - キーワード専用
            -- 位置専用

ここで、"/" と "*" はオプションです。使用された場合、これらの記号は、
引数が関数に渡される方法、すなわち、位置専用、位置またはキーワード、キ
ーワード専用、といった引数の種類を示します。キーワード引数は、名前付き
引数とも呼ばれます。


4.9.3.1. 位置またはキーワード引数
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

関数定義に "/" も "*" もない場合は、引数は位置またはキーワードで関数に
渡されます。


4.9.3.2. 位置専用引数
~~~~~~~~~~~~~~~~~~~~~

これをもう少し詳しく見てみると、特定の引数を *位置専用* と印を付けられ
ます。 *位置専用* の場合、引数の順序が重要であり、キーワードで引数を渡
せません。 位置専用引数は "/" （スラッシュ）の前に配置されます。 "/"
は、位置専用引数を残りの引数から論理的に分離するために使用されます。
関数定義に "/" がない場合、位置専用引数はありません。

"/" の後の引数は、 *位置またはキーワード* 、もしくは、 *キーワード専用
* です。


4.9.3.3. キーワード専用引数
~~~~~~~~~~~~~~~~~~~~~~~~~~~

引数をキーワード引数で渡す必要があることを示す *キーワード専用* として
引数をマークするには、引数リストの最初の *キーワード専用* 引数の直前に
"*" を配置します。


4.9.3.4. 関数の例
~~~~~~~~~~~~~~~~~

"/" および "*" といったマーカーに注意を払って、次の関数定義の例を見て
ください:

   >>> def standard_arg(arg):
   ...     print(arg)
   ...
   >>> def pos_only_arg(arg, /):
   ...     print(arg)
   ...
   >>> def kwd_only_arg(*, arg):
   ...     print(arg)
   ...
   >>> def combined_example(pos_only, /, standard, *, kwd_only):
   ...     print(pos_only, standard, kwd_only)

最も馴染みのある形式の最初の関数定義 "standard_arg"  は、呼び出し規約
に制限を設けておらず、引数は位置またはキーワードで渡されます:

   >>> standard_arg(2)
   2

   >>> standard_arg(arg=2)
   2

2番目の関数の "pos_only_arg" は、 "/" が関数定義にあるので、引数は位置
専用になります:

   >>> pos_only_arg(1)
   1

   >>> pos_only_arg(arg=1)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: pos_only_arg() got some positional-only arguments passed as keyword arguments: 'arg'

3番目の関数 "kwd_only_arg" は、関数定義に "*" があるので、引数はキーワ
ード専用になります:

   >>> kwd_only_arg(3)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: kwd_only_arg() takes 0 positional arguments but 1 was given

   >>> kwd_only_arg(arg=3)
   3

そして最後の関数は3つの引数の種類を一つの関数定義の中で使用しています:

   >>> combined_example(1, 2, 3)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: combined_example() takes 2 positional arguments but 3 were given

   >>> combined_example(1, 2, kwd_only=3)
   1 2 3

   >>> combined_example(1, standard=2, kwd_only=3)
   1 2 3

   >>> combined_example(pos_only=1, standard=2, kwd_only=3)
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: combined_example() got some positional-only arguments passed as keyword arguments: 'pos_only'

最後に、位置引数 "name" と "name" をキーとして持つ "**kwds" の間に潜在
的な衝突がある関数定義を考えてみましょう。

   def foo(name, **kwds):
       return 'name' in kwds

キーワードに "'name'" を入れても、先頭の引数と同じになってしまうため、
この関数が "True" を返すような呼び出しの方法はありません。例えば、次の
ようになってしまいます:

   >>> foo(1, **{'name': 2})
   Traceback (most recent call last):
     File "<stdin>", line 1, in <module>
   TypeError: foo() got multiple values for argument 'name'
   >>>

しかし位置専用を示す "/" を使用すれば可能になります。 "name" は位置引
数として、そして "'name'" はキーワード引数のキーワードとして認識される
からです:

   >>> def foo(name, /, **kwds):
   ...     return 'name' in kwds
   ...
   >>> foo(1, **{'name': 2})
   True

言い換えると、位置専用引数であれば、その名前を "**kwds" の中で使用して
も、曖昧にならないということです。


4.9.3.5. 要約
~~~~~~~~~~~~~

使用例で、関数定義でどの種類の引数を使うかべきかがわかると思います:

   def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):

ガイドとしては、

* もし引数の名前をユーザーに知らせる必要がないなら、位置専用引数を使用
  しましょう。これは引数の名前がユーザーにとって意味がなく、関数が呼ば
  れたときの引数の順序が問題であり、または、位置引数と任意のキーワード
  を使用する必要がある場合に便利です。

* 引数の名前に意味があり、それにより関数の定義がより明らかになる、また
  は、ユーザーが引数の順番に縛られることを避けたほうがいいと考えるのな
  ら、キーワード専用引数を使用しましょう。

* APIの場合、将来引数の名前が変更された場合にAPIの変更ができなくなるこ
  とを防ぐために、位置専用引数を使用しましょう。


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

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

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

通常このような *可変* 引数は、関数に渡される入力引数の残りを全て掬い取
るために、仮引数リストの最後に置かれます。 "*args" 引数の後にある仮引
数は 'キーワード専用' 引数で、位置引数ではなくキーワード引数としてのみ
使えることを意味します。

   >>> def concat(*args, sep="/"):
   ...     return sep.join(args)
   ...
   >>> concat("earth", "mars", "venus")
   'earth/mars/venus'
   >>> concat("earth", "mars", "venus", sep=".")
   'earth.mars.venus'


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

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

   >>> list(range(3, 6))            # 個別に引数を指定する通常の関数呼び出し
   [3, 4, 5]
   >>> args = [3, 6]
   >>> list(range(*args))            # 引数リストをアンパックして関数呼び出し
   [3, 4, 5]

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

   >>> def parrot(voltage, state='a stiff', action='voom'):
   ...     print("-- This parrot wouldn't", action, end=' ')
   ...     print("if you put", voltage, "volts through it.", end=' ')
   ...     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.9.6. ラムダ式
---------------

キーワード "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

The above example uses a lambda expression to return a function.
Another use is to pass a small function as an argument.  For instance,
"list.sort()" takes a sorting key function *key* which can be a lambda
function:

   >>> 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.9.7. ドキュメンテーション文字列
---------------------------------

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

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

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

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.9.8. 関数のアノテーション
---------------------------

関数アノテーション はユーザ定義関数で使用される型についての完全にオプ
ションなメタデータ情報です (詳細は **PEP 3107** と **PEP 484** を参照
してください)。

*Annotations* are stored in the "__annotations__" attribute of the
function as a dictionary and have no effect on any other part of the
function.  Parameter annotations are defined by a colon after the
parameter name, followed by an expression evaluating to the value of
the annotation.  Return annotations are defined by a literal "->",
followed by an expression, between the parameter list and the colon
denoting the end of the "def" statement.  The following example has a
required argument, an optional argument, and the return value
annotated:

   >>> def f(ham: str, eggs: str = 'eggs') -> str:
   ...     print("Annotations:", f.__annotations__)
   ...     print("Arguments:", ham, eggs)
   ...     return ham + ' and ' + eggs
   ...
   >>> f('spam')
   アノテーション: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
   引数: spam eggs
   'spam and eggs'


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

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

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

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

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

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

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

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

* 可能なら、コメントは行に独立で書くこと。

* docstring を使うこと。

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

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

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

* 同様に、ほんの少しでも他の言語を話す人がコードを読んだりメンテナンス
  する可能性があるのであれば、非 ASCII 文字も識別子に使うべきではあり
  ません。

-[ 脚注 ]-

[1] 実のところ、*オブジェクトへの参照渡し (call by object reference)*
    という言ったほうがより正確です。というのは、変更可能なオブジェクト
    が渡されると、呼び出された側の関数がオブジェクトに行った変更 (例え
    ばリストに挿入された要素) はすべて、関数の呼び出し側にも反映される
    からです。
