Day 81:型ヒント ― 「Pythonでも、型を言葉にして伝えてみる」
Day 81では、昨日少し触れた 型ヒント を、もう一歩深く掘り下げていきます。
今日のキーワードはこの6つです。
strintlistdictOptional- 関数の型指定
「型」と聞くと、ちょっと堅い印象があるかもしれませんが、 型ヒントはむしろ、
「この関数は、こういう値を受け取って、こういう値を返すよ」
と、コードに“やさしい説明書”を付けるようなイメージです。
型ヒントの基本 ― 「型を明示すると、コードの意図がくっきりする」
なぜ型ヒントを使うのか
Pythonは「動的型付け」の言語なので、 型を書かなくても動きます。
def add(a, b):
return a + b
Pythonこれでも、もちろん実行できます。
でも、少し時間が経ってからこのコードを見たとき、
aとbは本当に数値なのか?- 文字列を渡してもいいのか?
- 戻り値は整数?小数?文字列?
といった疑問が、じわじわ湧いてきます。
そこで登場するのが 型ヒント です。
def add(a: int, b: int) -> int:
"""
2つの整数 a, b を足し算して返します。
"""
return a + b
Pythonこう書くことで、
aとbは整数を想定している- 戻り値も整数である
という「約束」が、コードの中に明示されます。
「自分の頭の中にある前提を、コードに書き出しておく」
それが型ヒントのいちばん大きな役割です。
基本の型ヒント:str と int ― 「文字と数字をはっきりさせる」
str の型ヒント
文字列を扱う関数に、str の型ヒントを付けてみましょう。
def greet(name: str) -> str:
"""
名前(文字列)を受け取り、挨拶文(文字列)を返します。
"""
return f"こんにちは、{name}さん!"
Pythonname: str→ 引数nameは文字列-> str→ 戻り値も文字列
ということが、ひと目で分かります。
int の型ヒント
整数を扱う関数なら、int を使います。
def double(n: int) -> int:
"""
整数 n を2倍にして返します。
"""
return n * 2
Pythonここでのポイントは、
- 「この関数は、数値を受け取って数値を返す」という意図が明確になる
- 間違って文字列を渡したとき、型チェックツール(mypyなど)が教えてくれる
というところです。
コレクションの型ヒント:list と dict ― 「中身の型まで伝える」
list の型ヒント ― 「何のリストなのか」を書く
リストは、型ヒントを付けるときに 「中身の型」 まで書くのがポイントです。
Python 3.9以降なら、こんな書き方ができます。
def sum_numbers(numbers: list[int]) -> int:
"""
整数のリストを受け取り、その合計を返します。
numbers: [1, 2, 3] のような整数リストを想定しています。
"""
total = 0
for n in numbers:
total += n
return total
Pythonlist[int]→ 「整数のリスト」という意味numbersの中身が「数値であること」を前提にできる
これによって、
numbersに文字列が混ざっていると、型チェックで警告が出る- コードを読む人も「このリストは何のリストか」をすぐ理解できる
というメリットがあります。
dict の型ヒント ― 「キーと値の型」をセットで書く
辞書(dict)は、キーと値の型をセットで指定します。
def get_user_name(user: dict[str, str]) -> str:
"""
ユーザー情報の辞書から、nameキーの値を取り出して返します。
user は {"name": "Taro", "email": "[email protected]"} のような辞書を想定しています。
"""
return user["name"]
Pythondict[str, str]→ 「キーも値も文字列」の辞書user["name"]が文字列であることを期待している
もう少し複雑な例も見てみましょう。
def get_price(product: dict[str, int]) -> int:
"""
商品情報の辞書から、priceキーの値(整数)を取り出して返します。
product は {"name": "Apple", "price": 120} のような辞書を想定しています。
"""
return product["price"]
Pythondict[str, int]→ 「キーは文字列、値は整数」の辞書product["price"]は整数であることが前提
こうして「キーと値の型」を明示しておくと、 辞書の使い方を間違えたときに、型チェックツールが気づいてくれます。
Optional ― 「値があるかもしれないし、ないかもしれない」
Optionalとは何か
Optional は、
「その値が、あるときもあれば、
Noneのときもある」
という状況を表す型ヒントです。
Pythonでは、None が「何もない」を表す特別な値ですが、 型ヒントの世界では、
「この変数は、
strかもしれないし、Noneかもしれない」
ということを、Optional[str] のように書きます。
Optionalの基本例
from typing import Optional
def find_user_name(user_id: int) -> Optional[str]:
"""
ユーザーIDから名前を検索して返します。
見つかった場合は名前(str)、見つからなかった場合は None を返します。
"""
# ここでは仮のデータベースとして辞書を使います
users = {
1: "Taro",
2: "Hanako",
}
# user_id が辞書に存在する場合は名前を返し、存在しない場合は None を返します
return users.get(user_id)
Python-> Optional[str]→ 戻り値は「文字列かもしれないし、Noneかもしれない」- 実際に
users.get(user_id)は、キーがなければNoneを返す
この関数を使う側は、
name = find_user_name(3)
if name is None:
print("ユーザーが見つかりませんでした")
else:
print(f"ユーザー名は {name} です")
Pythonのように、
「Noneの可能性をちゃんと考える」
書き方になります。
セキュリティ・安全性の観点から見たOptional
Optional を使って「Noneの可能性」を明示しておくと、
- 「存在しない値を前提に処理を書いてしまう」
- 「Noneに対してメソッドを呼んでエラーになる」
といったバグを減らせます。
「値がないかもしれない」という事実を、型で表現しておく
これは、コードの安全性を高めるうえで、とても大切な考え方です。
関数の型指定 ― 「引数と戻り値の“契約書”を書く」
関数の型指定の基本形
関数の型指定は、
**「引数の型」と「戻り値の型」をセットで書く」
のが基本です。
一般的な形はこんな感じ。
def 関数名(引数名: 型, 引数名2: 型2, ...) -> 戻り値の型:
...
Python具体例をいくつか見ていきましょう。
例1:シンプルな数値計算
def add(a: int, b: int) -> int:
"""
2つの整数 a, b を足し算して返します。
"""
return a + b
Pythona: int, b: int→ 整数を受け取る-> int→ 整数を返す
例2:リストを受け取って、平均値を返す
def average(values: list[float]) -> float:
"""
浮動小数点数のリスト values の平均値を返します。
values が空リストの場合は ZeroDivisionError が発生します。
"""
total = 0.0
for v in values:
total += v
return total / len(values)
Pythonvalues: list[float]→ 「浮動小数点数のリスト」を受け取る-> float→ 平均値(浮動小数点数)を返す
例3:Optionalを使った関数の型指定
from typing import Optional
def get_config_value(key: str) -> Optional[str]:
"""
設定値をキーで検索して返します。
見つかった場合は文字列、見つからない場合は None を返します。
"""
config = {
"APP_NAME": "SampleApp",
"ENV": "development",
}
return config.get(key)
Pythonkey: str→ キーは文字列-> Optional[str]→ 戻り値は「文字列かNone」
この関数を使う側は、 「Noneの可能性」を意識したコードになります。
value = get_config_value("SECRET_KEY")
if value is None:
print("SECRET_KEY が設定されていません")
else:
print(f"SECRET_KEY は {value} です")
PythonDay 81ミニテンプレート ― 型ヒント練習セット
最後に、今日の内容をひとまとめにした 「型ヒントミニテンプレート」 を載せておきます。
1. 基本の型ヒント(str / int)
bash
mkdir day81_type_hints
cd day81_type_hints
bash
cat << 'EOF' > basic_types.py
def greet(name: str) -> str:
"""
名前(文字列)を受け取り、挨拶文(文字列)を返します。
"""
return f"こんにちは、{name}さん!"
def double(n: int) -> int:
"""
整数 n を2倍にして返します。
"""
return n * 2
EOF
2. list と dict の型ヒント
bash
cat << 'EOF' > collections_types.py
def sum_numbers(numbers: list[int]) -> int:
"""
整数のリスト numbers の合計を返します。
"""
total = 0
for n in numbers:
total += n
return total
def get_user_name(user: dict[str, str]) -> str:
"""
ユーザー情報の辞書 user から、nameキーの値を取り出して返します。
user は {"name": "Taro", "email": "[email protected]"} のような辞書を想定しています。
"""
return user["name"]
EOF
3. Optional と関数の型指定
bash
cat << 'EOF' > optional_types.py
from typing import Optional
def find_user_name(user_id: int) -> Optional[str]:
"""
ユーザーIDから名前を検索して返します。
見つかった場合は名前(str)、見つからなかった場合は None を返します。
"""
users = {
1: "Taro",
2: "Hanako",
}
return users.get(user_id)
def demo() -> None:
"""
find_user_name の動作を確認するデモ関数です。
戻り値の型は None(何も返さない)としています。
"""
name1 = find_user_name(1)
name2 = find_user_name(3)
if name1 is not None:
print(f"ID 1 のユーザー名は {name1} です")
else:
print("ID 1 のユーザーは見つかりませんでした")
if name2 is not None:
print(f"ID 3 のユーザー名は {name2} です")
else:
print("ID 3 のユーザーは見つかりませんでした")
if __name__ == "__main__":
demo()
EOF
Day 81のまとめ ― 「型ヒントは、コードに添える“やさしい説明書”」
今日の主役は、
str/int:基本的な型ヒントlist/dict:中身の型まで伝えるコレクションの型ヒントOptional:値が「あるかもしれないし、ないかもしれない」を表現する型- 関数の型指定:引数と戻り値の「契約書」をコードに書くこと
でした。
型ヒントを使い始めると、
- 「この関数は、何を受け取って、何を返すのか」がくっきり見えてくる
- 型チェックツールが、バグの芽を早めに教えてくれる
- 自分のコードに、少し“プロっぽさ”が宿ってくる
そんな感覚が、少しずつ育っていきます。
Day 81でこの感覚をつかんだことで、 これから書いていく関数は、
「ただ動くだけじゃなく、意図がはっきり伝わるもの」
へと、静かに変わっていきます。
型ヒントは、 未来の自分と仲間への、 ちいさな「思いやりのメモ」です。
少しずつ、でも確実に、 コードにそのメモを増やしていきましょう。

