【Python3エンジニア認定基礎試験】4. その他の制御フローツール

4.1. if 文
---
if文は、条件に基づいて異なるコードを実行するための基本的な方法です。
以下の例では、整数が0より小さい場合、0に変更する処理を行っています。

```
x = int(input("Please enter an integer: "))

if x < 0:
    x = 0
    print('Negative changed to zero')
elif x == 0:
    print('Zero')
elif x == 1:
    print('Single')
else:
    print('More')
```

if文は条件がTrueのときにコードブロックを実行します。
elifはelse ifの略で、追加の条件を指定します。
elseは全ての条件がFalseの場合に実行されます。

4.2. for 文
---
Pythonのfor文は、リストや文字列のようなシーケンス型のオブジェクトを反復処理します。以下の例では、文字列リストの各要素とその長さを表示します。

```
words = ['cat', 'window', 'defenestrate']
for w in words:
    print(w, len(w))    
```

Pythonのfor文は、他の言語におけるカウンタ制御ループよりも、シーケンス内の各要素に直接アクセスできる点で便利です。

4.3. range() 関数
---
range()関数は数列を生成し、それをfor文で使用することで、指定範囲内の整数を反復処理できます。

```
for i in range(5):
    print(i)
range(start, stop, step)の形で、開始値、終了値、ステップ幅を指定できます。
```

4.4. break 文と continue 文とループの else 節
---
break文はループを即座に終了させます。
continue文は次のイテレーションにスキップします。
ループのelse節は、ループが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:
        print(n, 'is a prime number')        
```

4.5. pass 文
---
pass文は何もしない文です。構文的に文が必要な場所で、実行時には何もさせたくない場合に使用します。

```
while True:
    pass  # 忙しい待機（Ctrl+Cで中断）
```

4.6. 関数を定義する
---
関数は、再利用可能なコードの塊を作るために使用されます。以下はフィボナッチ数列を生成する関数です。

```
def fib(n):
    """n以下のフィボナッチ数列を表示"""
    a, b = 0, 1
    while a < n:
        print(a, end=' ')
        a, b = b, a + b
    print()

fib(2000)
```
defキーワードで関数を定義し、関数名と引数を続けます。
関数の内部でローカル変数が使用され、関数が終了するとこれらの変数は破棄されます。

4.7. 関数定義についてもう少し
---
4.7.1. デフォルトの引数値
---
関数にデフォルトの引数値を設定することができます。

```
def ask_ok(prompt, retries=4, reminder='Please try again!'):
    while retries > 0:
        ok = input(prompt)
        if ok in ('y', 'ye', 'yes'):
            return True
        if ok in ('n', 'no', 'nop', 'nope'):
            return False
        retries -= 1
        print(reminder)
    raise ValueError('invalid user response')
```

4.7.2. キーワード引数
---
関数呼び出し時に、キーワードを使って引数に値を渡すことができます。

```
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, "!")

parrot(voltage=1000)
parrot(voltage=1000000, action='VOOOOOM')
```
キーワード引数は、関数が期待する引数名と一致する必要があります。

4.7.2. キーワード引数
---
先ほどの例の最後に示したように、キーワード引数は位置引数の後に指定する必要があります。
また、キーワード引数として渡された値は、その関数で定義されている引数のいずれかに対応していなければなりません。
位置引数とキーワード引数を組み合わせる場合、位置引数をすべて指定した後にキーワード引数を指定することができます。

関数が呼び出されるとき、すべての位置引数は定義されている順序で対応するパラメータに割り当てられ、キーワード引数は関数のシグネチャで指定された名前に基づいて割り当てられます。
このプロセスが完了した後、残りの引数はオプションのデフォルト値を持つ引数に割り当てられます。

4.7.3. 任意の引数リスト
---
関数が呼び出されるときに、与える引数の数が変動する場合があります。これは、引数のリストをタプルとして受け取る *name 構文を使って実現できます。たとえば、以下の関数は変数個数の引数を受け付け、そのすべての引数の合計を計算します。

```
>>> def write_multiple_items(file, separator, *args):
...     file.write(separator.join(args))
...
```
*args は位置引数をタプルとして受け取り、args はタプルの要素としてリストされます。以下のように関数を呼び出すことができます。

```
>>> write_multiple_items('file', ',', 'item1', 'item2', 'item3')
```
これにより、file.write() に渡される文字列は 'item1,item2,item3' になります。

また、キーワード引数を辞書として受け取ることも可能です。
この場合は **name 構文を使います。以下の関数は、任意のキーワード引数を受け取ります。

```
>>> def parrot(voltage, state='a stiff', action='voom', type='Norwegian Blue', **kwargs):
...     print("-- This parrot wouldn't", action, end=' ')
...     print("if you put", voltage, "volts through it.")
...     print("-- Lovely plumage, the", type)
...     print("-- It's", state, "!")
...     for kw in kwargs:
...         print(f"-- {kw}: {kwargs[kw]}")
...
>>> parrot(1000, type="African Grey", time="10:00 AM", user="John")
-- This parrot wouldn't voom if you put 1000 volts through it.
-- Lovely plumage, the African Grey
-- It's a stiff!
-- time: 10:00 AM
-- user: John
```
この関数は、通常の引数の他に任意の数のキーワード引数を受け付けます。

4.7.4. 引数リストのアンパッキング
---
関数を呼び出す際に、既存のシーケンスを個別の引数として渡したい場合があります。その場合は、引数の前に * を付けて呼び出すことができます。

```
>>> 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.")
...     print("-- It'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.
-- It's bleedin' demised!
```
このように、* や ** を使うことで、引数のアンパッキングが可能になります。

4.7.5 関数の定義における任意の引数リストの受け取り
---
関数定義では、位置引数とキーワード引数の組み合わせに加え、任意の数の引数を受け取ることができます。これを実現するためには、以下のように記述します。

任意の位置引数 (*args):
関数が可変個数の位置引数を受け取る場合、* を引数名の前に付けます。この引数はタプルとして受け取られます。

```
def concat(*args, sep="/"):
    return sep.join(args)

print(concat("earth", "mars", "venus"))
# Output: 'earth/mars/venus'
print(concat("earth", "mars", "venus", sep="."))
# Output: 'earth.mars.venus'
```

任意のキーワード引数 (**kwargs):
関数が可変個数のキーワード引数を受け取る場合、** を引数名の前に付けます。この引数は辞書として受け取られます。

```
def print_dict(**kwargs):
    for key, value in kwargs.items():
        print(f"{key}: {value}")

print_dict(name="Alice", age=30, job="Engineer")
# Output:
# name: Alice
# age: 30
# job: Engineer
```

4.7.6 ラムダ式
---
Pythonでは、lambda キーワードを使って、無名関数（名前のない関数）を作成することができます。
ラムダ式は短くて簡潔な関数を定義するのに役立ちます。

構文:
```
lambda 引数1, 引数2, ... : 式
```

```
def make_incrementor(n):
    return lambda x: x + n

f = make_incrementor(42)
print(f(0))  # Output: 42
print(f(1))  # Output: 43
```

ラムダ式は、特に一時的に使用するための簡単な関数を作成する際に便利です。

4.7.7 ドキュメンテーション文字列 (Docstrings)
---
関数の冒頭に文字列リテラルを記述することで、その関数のドキュメンテーション文字列 (docstring) を定義することができます。この文字列は関数の使用方法や動作を説明するために使用されます。

```
def my_function():
    """ここに関数の説明を記述します。
    
    詳細な説明が必要な場合は、複数行で記述することもできます。
    """
    pass

print(my_function.__doc__)
```
ドキュメンテーション文字列は、help() 関数や IDE のツールチップで参照されるため、関数の使い方を他の人や将来の自分に伝えるために非常に有用です。

4.8 関数注釈
---
関数注釈 (function annotations) は、関数の引数や戻り値に対するメタデータを提供するための機能です。関数注釈は、引数名の後にコロン (:) を付けて型や説明を記述し、戻り値の型は矢印 (->) の後に記述します。

```
def greeting(name: str) -> str:
    return 'Hello ' + name

print(greeting("Alice"))
# Output: Hello Alice

print(greeting.__annotations__)
# Output: {'name': <class 'str'>, 'return': <class 'str'>}
```

関数注釈は、型ヒントとして使われることが一般的ですが、Python自体は注釈を強制しません。
これにより、コードの可読性と保守性が向上します。

https://qiita.com/FT_log/items/d9b4fed10531c6a08c1d