導入
Python は変数の型を書かなくても動く言語ですが、大きなプログラムやチーム開発では「この引数は何の型を想定しているか」が分からず読みづらくなることがあります。**型ヒント(type hint)**は、コードにその意図を書き添える仕組みです。
説明
関数の引数や戻り値には : 型 と -> 型 で注釈を付けられます。変数にも 変数名: 型 = 値 の形で付けられます。
def greet(name: str, times: int = 1) -> str:
return f"こんにちは、{name}さん!" * times
message: str = greet("太郎", times=2)
print(message)
count: int = 3
print(count)
ここが重要なポイントです。型ヒントは実行時に強制されません。Python はあくまで動的型付け言語で、型ヒントは「人間(と、あとで紹介するツール)に向けたコメントのような注釈」です。試しに、わざと違う型を渡してみましょう。
def add(a: int, b: int) -> int:
return a + b
print(add("1", "2")) # 型ヒントは int だが、実際は文字列を渡してもエラーにならない
"1" + "2" は文字列の連結なので "12" が返ります。型ヒントに反していても、実行時にエラーにはなりません。それでも型ヒントには大きな価値があります。エディタが引数の型を教えてくれたり、mypy のような型チェッカーが「本来 int を渡すべき場所に str を渡している」と実行前に警告してくれたりするからです。実務のコードでは、型ヒントを前提にしたプロジェクトが増えています。
より複雑な型(「文字列のリスト」「int かもしれないし None かもしれない」など)を表すには、標準ライブラリの typing モジュールや、クラスに型ヒント付きの属性をまとめて書ける dataclasses モジュールがよく使われます。(この学習環境の実行エンジンには typing と dataclasses が用意されていないため、ここでは実行せず書き方だけ紹介します。)
from typing import List, Optional
from dataclasses import dataclass
def find_names(names: List[str], keyword: Optional[str] = None) -> List[str]:
if keyword is None:
return names
return [n for n in names if keyword in n]
@dataclass
class User:
name: str
age: int
u = User("太郎", 25)
print(u.name, u.age)
List[str] は「文字列のリスト」、Optional[str] は「文字列 または None」を表します。@dataclass は、__init__ を自分で書かなくても、型ヒント付きの属性の並びからクラスを自動生成してくれる便利な機能です。
やってみよう
greet や add の引数に渡す値の型を変えてみて、型ヒントに反していても実行できてしまうことを確かめましょう。
演習
price: float と、初期値 0.1 の tax: float を引数に取り、戻り値の型ヒントも -> float で指定した関数 calc_total を定義し、price * (1 + tax) を返すようにしてください。calc_total(1000) を表示すると 1100.0 になります。
ヒント1を見る
def calc_total(price: float, tax: float = 0.1) -> float: の中で return price * (1 + tax)。
ヒント2を見る
最後に print(calc_total(1000)) を書きます。