型ヒントを使ってソースの可視性をアップする

# 型ヒントとは

型ヒントでは、プログラム内に引数や戻り値に型を定義し、あたかも静的型付け言語のようなコーディングができる。
型ヒントはメタ情報のように扱われるため、実行されるプログラムには影響がない。

pythonでは基本的に型を書くことはない。それはpythonが動的型付け言語とされているためである。
動的型付けとはプログラム実行時にpythonが型を判別し、適切な型を選択していることである。
⇔静的型付け･･･コンパイル時に型を判定する。対象言語はCやJava。

# 型ヒントを使用する目的

## ソースコードの可視性向上

pythonにも型の概念はあるものの、型を意識せずにプログラムを書ける。
しかし、型を意識しないでプログラムを書くと、データの構造が漏れていたり処理内容が間違っていることに気付きにくい。
実行時に想定外のエラーが発生しても原因を特定しづらい。
レビューにおいても作成したプログラムの本質や目的が第三者にも伝わりにくい。

型ヒントを用いることで、クラスや関数の引数がより明確になる。プログラムの意図がより伝わりやすくなる。
ソースファイルが多ければ多いほど効果がある。

## 開発効率の向上

help()でプログラムを調べる際、付与した型ヒントが表示できる。

* 型ヒントなし

```nohint.py

# 戻り値あり
def getword(name, age):
    return f"私は{name}です。{age}歳です。"

# 戻り値なし
def outputword(name, age):
    print(f"私は{name}です。{age}歳です。")

if __name__ == "__main__":
    print(getword("テスト　太郎", 30))
    outputword("テスト　花子", 25)
```
---
```
$ python
Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import nohint
>>> help(nohint)
Help on module nohint:

NAME
    nohint - # 戻り値あり

FUNCTIONS
    getword(name, age)
        # 戻り値あり

    outputword(name, age)
        # 戻り値なし

FILE
    c:\users\xxx\documents\nohint.py
```
</details>

* 型ヒントあり

```hintbase.py
from typing import NoReturn

# 戻り値あり
def getword(name : str, age : int) -> str:
    return f"私は{name}です。{age}歳です。"

# 戻り値なし
def outputword1(name : str, age : int):
    print(f"私は{name}です。{age}歳です。")

# 戻り値なし
def outputword2(name : str, age : int) -> None:
    print(f"私は{name}です。{age}歳です。")

# 戻り値なし
def outputword3(name : str, age : int) -> NoReturn:
    print(f"私は{name}です。{age}歳です。")

if __name__ == "__main__":
    print(getword("テスト　太郎", 30))
    outputword1("テスト　はなこ", 23)
    outputword2("テスト　まなこ", 24)
    outputword3("テスト　やまこ", 25)
```
---
```
$ python
Python 3.8.1 (tags/v3.8.1:1b293b6, Dec 18 2019, 23:11:46) [MSC v.1916 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import hintbase
>>> help(hintbase)
Help on module hintbase:

NAME
    hintbase

FUNCTIONS
    getword(name: str, age: int) -> str
        # 戻り値あり

    outputword1(name: str, age: int)
        # 戻り値なし

    outputword2(name: str, age: int) -> None
        # 戻り値なし

    outputword3(name: str, age: int) -> NoReturn
        # 戻り値なし

DATA
    NoReturn = typing.NoReturn

FILE
    c:\users\xxx\documents\hintbase.py
```

# 型ヒントを使うには

typingはpython3.5で追加されたモジュールなので最初から使用できる。
[typing公式](https://docs.python.org/ja/3.5/library/typing.html)

# 型ヒントの書き方

## 構文

```
def 関数名(引数名 : 型, 引数名 : 型, ...) -> 戻り値の型 :
```

引数名の後にコロンを付けて型名を書く。引数が複数ある場合はカンマで区切る。
戻り値がない場合は`None`や`NoReturn`とする。`-> 戻り値の型`は省略できる。
`NoReturn`を使用する場合はtypingからimportしておく必要がある。

```hint-base.py
from typing import NoReturn

# 戻り値あり
def getword(name : str, age : int) -> str:
    return f"私は{name}です。{age}歳です。"

# 戻り値なし
def outputword1(name : str, age : int):
    print(f"私は{name}です。{age}歳です。")

# 戻り値なし
def outputword2(name : str, age : int) -> None:
    print(f"私は{name}です。{age}歳です。")

# 戻り値なし
def outputword3(name : str, age : int) -> NoReturn:
    print(f"私は{name}です。{age}歳です。")

if __name__ == "__main__":
    print(getword("テスト　太郎", 30))
    outputword1("テスト　はなこ", 23)
    outputword2("テスト　まなこ", 24)
    outputword3("テスト　やまこ", 25)
```
---
```
$ python hint-base.py
私はテスト　太郎です。30歳です。
私はテスト　はなこです。23歳です。
私はテスト　まなこです。24歳です。
私はテスト　やまこです。25歳です。
```

## 自作クラスの場合

自作クラス内のメソッドでは第１引数が`self`となるが、`self`には型ヒントは不要。
クラスメソッドも同様で、第１引数の`cls`にも型ヒントは不要。

```hint-class.py
from typing import Type, NoReturn

class Words:

    # コンストラクタ
    def __init__(self, name : str, age : int):
        self.name = name
        self.age = age

    # 戻り値あり
    def getword(self) -> str:
        return f"私は{self.name}です。{self.age}歳です。"

    # 戻り値なし
    def setword(self, name : str, age : int) -> NoReturn:
        self.name = name
        self.age = age

if __name__ == "__main__":
    words = Words("テスト　太郎", 30)
    print(words.getword())
    words.setword("テスト　はなこ", 23)
    print(words.getword())
```
---
```
$ python hint-class.py
私はテスト　太郎です。30歳です。
私はテスト　はなこです。23歳です。
```