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" 文は、任意の
シーケンス型 (リストまたは文字列) にわたって反復を行います。反復の順番
はシーケンス中に要素が現れる順番です。例えば:

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

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

   # Create a sample collection
   users = {'Hans': 'active', 'Éléonore': 'inactive', '景太郎': 'active'}

   # Strategy:  Iterate over a copy
   for user, status in users.copy().items():
       if status == 'inactive':
           del users[user]

   # Strategy:  Create a new collection
   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" and "continue" Statements, and "else" Clauses on Loops
===================================================================

The "break" statement breaks out of the innermost enclosing "for" or
"while" loop.

A "for" or "while" loop can include an "else" clause.

In a "for" loop, the "else" clause is executed after the loop reaches
its final iteration.

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

In either kind of loop, the "else" clause is **not** executed if the
loop was terminated by a "break".

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

   >>> 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

(Yes, this is the correct code.  Look closely: the "else" clause
belongs to the "for" loop, **not** the "if" statement.)

When used with a loop, the "else" clause has more in common with the
"else" clause of a "try" statement than it does with that of "if"
statements: a "try" statement's "else" clause runs when no exception
occurs, and a loop's "else" clause runs when no "break" occurs. For
more on the "try" statement and exceptions, see 例外を処理する.

The "continue" statement, also borrowed from C, continues with the
next iteration of the loop:

   >>> for num in range(2, 10):
   ...     if num % 2 == 0:
   ...         print("Found an even number", num)
   ...         continue
   ...     print("Found an odd number", num)
   ...
   Found an even number 2
   Found an odd number 3
   Found an even number 4
   Found an odd number 5
   Found an even number 6
   Found an odd number 7
   Found an even number 8
   Found an odd 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. "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.

最も単純な形式は、対象の値に対して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. If no case matches, none of the branches is
executed.

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

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

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

   # point is an (x, y) tuple
   match point:
       case (0, 0):
           print("Origin")
       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("Not a point")

このコードは注意して見てください！ 最初のパターンには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("Origin")
           case Point(x=0, y=y):
               print(f"Y={y}")
           case Point(x=x, y=0):
               print(f"X={x}")
           case Point():
               print("Somewhere else")
           case _:
               print("Not a point")

いくつかの組み込みクラスでは位置引数が使用でき、属性の順番を提供します
(例: データクラス)。クラスの "__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("No points")
       case [Point(0, 0)]:
           print("The origin")
       case [Point(x, y)]:
           print(f"Single point {x}, {y}")
       case [Point(0, y1), Point(0, y2)]:
           print(f"Two on the Y axis at {y1}, {y2}")
       case _:
           print("Something else")

パターンに "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"Not on the diagonal")

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

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

* シーケンスパターンは拡張アンパックをサポート: "[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.7. 関数を定義する
===================

フィボナッチ数列 (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, end=' ')
   ...         a, b = b, a+b
   ...     print()
   ...
   >>> # 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" 文で指定されていたり、外側の関数の変数が "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):  # 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" オブジェクトの *メソッド*
  が呼び出されます。メソッドとは、オブジェクトに「属する」関数のことで
  あり、 "obj.methodname" と表されます。ここで、 "obj" は何らかのオブ
  ジェクト (式の場合もあります) であり、 "methodname" はそのオブジェク
  トの型で定義されたメソッド名です。色々な型がそれぞれ独自のメソッドを
  定義しています。異なる型が同じ名前のメソッドを持つことも可能であり、
  どちらの方のものであるかという曖昧さは生まれません。(>>*<<クラス*を
  使って独自の型やメソッドを自分で定義することもできます。参照: クラス
  ) 例にある "append()" メソッドは、リストオブジェクトに対して定義され
  ているもので、リストの末尾に新しい要素を追加します。この例では
  "result = result + [a]" と等価ですが、計算効率の上ではベターです。


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

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


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

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

   def ask_ok(prompt, retries=4, reminder='Please try again!'):
       while True:
           ok = 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 ValueError('invalid user response')
           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.8.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 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 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.8.3. 特殊なパラメータ
-----------------------

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

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

   def f(pos1, pos2, /, pos_or_kwd, *, kwd1, kwd2):
         -----------    ----------     ----------
           |             |                  |
           |        Positional or keyword   |
           |                                - Keyword only
            -- Positional only

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


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

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


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

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

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


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

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


4.8.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'

The third function "kwd_only_args" only allows keyword arguments as
indicated by a "*" in the function definition:

   >>> 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.8.3.5. 要約
~~~~~~~~~~~~~

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

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

ガイドとしては、

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

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

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


4.8.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.8.5. 引数リストのアンパック
-----------------------------

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

   >>> list(range(3, 6))            # normal call with separate arguments
   [3, 4, 5]
   >>> args = [3, 6]
   >>> list(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, 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.8.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:

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

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

*アノテーション* は、関数の "__annotations__" 属性に辞書として格納され
、関数の他の部分には影響しません。 パラメータアノテーションは、パラメ
ータ名のあとのコロンと式で定義され、その式の評価結果がアノテーションと
なります。 戻り値アノテーションは、パラメータリストと "def" 文の終わり
を表すコロンの間で、 "->" の後ろに式を書くことで定義されます。 次の例
では、必須引数と任意引数、戻り値にアノテーションが付与されています:

   >>> def f(ham: str, eggs: str = 'eggs') -> str:
   ...     print("Annotations:", f.__annotations__)
   ...     print("Arguments:", ham, eggs)
   ...     return ham + ' and ' + eggs
   ...
   >>> f('spam')
   Annotations: {'ham': <class 'str'>, 'return': <class 'str'>, 'eggs': <class 'str'>}
   Arguments: spam eggs
   'spam and eggs'


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

これからより長くより複雑な 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)*
    という言ったほうがより正確です。というのは、変更可能なオブジェクト
    が渡されると、呼び出された側の関数がオブジェクトに行った変更 (例え
    ばリストに挿入された要素) はすべて、関数の呼び出し側にも反映される
    からです。
