つよつよエンジニア「Pythonのコードに型アノテーションをつけるといいね」

# リリース3日前、社内――
つよつよエンジニア「これって型アノテーションをつけるといいね」
俺「リリース３日前に！？（はい！　わかりました！）」

俺はPythonでの型アノテーションのやり方をググっていた――。

# 型アノテーションとは

型アノテーションとは、変数や関数の引数・戻り値に型に関するコメントをつけることである。
Python3.6 から追加された機能らしい。

あくまでもコメントであり、動作には影響を及ぼさないが、リッチなエディタ（PyCharm や VSCode ）は空気を読んで「ピッピー！　アノテーション警察です！　あなた今intが入るべき奴にstrを入れましたね！」と取り締まりにやってきてくれる……はずだ。


>あくまでコーディング中にのみ利用できる機能になりますが、コードの可読性や品質が向上するため Python でプログラムを開発する際には型アノテーションは必須と言えます。

[Hakky Handbook Pythonで型アノテーションを使う](https://book.st-hakky.com/hakky/type-annotation/#:~:text=%E5%9E%8B%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%81%AF%E2%80%8B&text=%E3%81%AA%E3%81%8A%E3%80%81%E5%9E%8B%E3%82%A2%E3%83%8E%E3%83%86%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AF%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0,%E3%81%AF%E5%BF%85%E9%A0%88%E3%81%A8%E8%A8%80%E3%81%88%E3%81%BE%E3%81%99%E3%80%82
)

必須といえるらしい。

じゃあ今まで使ってなかった俺のプログラムって何なんだ。
任意だったでもいうのか？

しかし、なるほど、単にコメントを乗っけていくだけだから、ミスったとしても動作には影響が出ない（給与査定には影響が出るかもしれない）。

文法さえミスしなければ、リリース直前にやっても影響範囲は小さそうである。

# アノテーションのやり方
floatとかの、単純な型については例えばこうなる。

アノテーションなし
```python
rate = 0.9
```

アノテーションあり

```python
rate: float =0.9
```

単純な型なら、`:float`　というのを記述するだけだ。

さて……警告ってどんな感じに出るんだろうか？

**int変数に無理やり🍩を食べさせてみた。**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/65af2e56-babc-8544-ae6c-a0126f5a6e64.png)

思ってた以上には、下線部波線も出ないし、ｽｯ……と気配が消えたくらいだ。
飲み会のときの俺の挙動と似ている。
どうも、VSCodeの拡張機能の、Pylanceがやってくれたらしい。
アノテーションのことがちょっと好きになってきた。

# ちょっと複雑なアノテーションの例（追記あり）

### ※Python3.10以前

ちょっと複雑なアノテーションをしたいときは、

```python
from typing import List, Dict, Optional

# Listの例
def get_names() -> List[str]:
    return ["Alice", "Bob", "Charlie"]

# Dictの例
def get_ages() -> Dict[str, int]:
    return {"Alice": 25, "Bob": 30, "Charlie": 35}

# Optionalの例
def find_student_name(student_id: int) -> Optional[str]:
    students = {1: "Alice", 2: "Bob", 3: "Charlie"}
    return students.get(student_id)
```

としていた。

（追記）
Python 3.9からは、リストや辞書の型アノテーションにはtypingモジュールからListやDictをインポートするのではなく、標準のコレクション型であるlistやdictを使用することが推奨されるようになった（コメントで教えてもらった。ありがとう！）


[What’s New In Python 3.9 — Type Hinting Generics in Standard Collections](https://docs.python.org/3.9/whatsnew/3.9.html#type-hinting-generics-in-standard-collections)
[typing — Support for type hints — Python 3.9.19 documentation](https://docs.python.org/3.9/library/typing.html#module-contents)

引用：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/bcac21db-a1eb-a0f6-5c83-0cffa35a3732.png)

### Python3.10以降の例

```python
# listの例
def get_names() -> list[str]:
    return ["Alice", "Bob", "Charlie"]

# dictの例
def get_ages() -> dict[str, int]:
    return {"Alice": 25, "Bob": 30, "Charlie": 35}

from typing import Optional

# Optionalの例
def find_student_name(student_id: int) -> Optional[str]:
    students = {1: "Alice", 2: "Bob", 3: "Charlie"}
    return students.get(student_id)

```

こうなるようだ。Optionalはそのままだ。

# 方法

俺は、ChatGPTに泣きついて何とかしてもらった。

といっても、全面的にやってもらったわけではなく、コードを渡して、WinMargeで比較して、ヘンな変更を入れられてないか確かめつつ1個1個行った。コメントが消されたり、一時的にコメントアウトしている部分が削られたりはしていたのだが、型のつけ間違いみたいなことは起こらなかった。
優秀だなあ。

# 感想
もともと、C言語->C++->C#という感じでプログラミングを学んできたので、はじめてPythonを触ったときには驚いた。

    a = 1

も、

    a = "なんとか"

も、どっちも書けてしまうもんな。

よく考えてみれば、たしかに、コンパイル時に右辺で何を入れられているかを見れば型指定は必要がない。

へー、すごいじゃんね、と思ったが、ところがあえて型指定をしようというのがPythonの型アノテーションである。
人間は、あまりに自由を与えられると困惑してしまうのかもしれない。

などと分かったことを言いつつ……Hakky Handbook Pythonがそう仰るならそうなのだろう。俺は長いものにはくるくるまかれていきたい。

# 追記：その２

>Pydanticなど型を参照しバリデーションする場合、動作に影響することがある
とコメントを頂いたので調べてみた。

Pydanticは、Python用のデータバリデーションおよびデータ解析ライブラリで、型を強制する効果がある。こういうのを導入すると、型アノテーションとはいえども動作に影響することがあるようだ。

# 参考
[typing --- 型ヒントのサポート](https://docs.python.org/ja/3/library/typing.html)
[Hakky Handbook Pythonで型アノテーションを使う](https://book.st-hakky.com/hakky/type-annotation/)