基礎から学ぶPython入門 90日コース | 実践開発 - Day 81:型ヒント

Python 90日で身につけるPython
スポンサーリンク
スポンサーリンク

Day 81:型ヒント ― 「Pythonでも、型を言葉にして伝えてみる」

Day 81では、昨日少し触れた 型ヒント を、もう一歩深く掘り下げていきます。

今日のキーワードはこの6つです。

  • str
  • int
  • list
  • dict
  • Optional
  • 関数の型指定

「型」と聞くと、ちょっと堅い印象があるかもしれませんが、 型ヒントはむしろ、

「この関数は、こういう値を受け取って、こういう値を返すよ」

と、コードに“やさしい説明書”を付けるようなイメージです。

型ヒントの基本 ― 「型を明示すると、コードの意図がくっきりする」

なぜ型ヒントを使うのか

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}さん!"
Python
  • name: 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
Python
  • list[int] → 「整数のリスト」という意味
  • numbers の中身が「数値であること」を前提にできる

これによって、

  • numbers に文字列が混ざっていると、型チェックで警告が出る
  • コードを読む人も「このリストは何のリストか」をすぐ理解できる

というメリットがあります。

dict の型ヒント ― 「キーと値の型」をセットで書く

辞書(dict)は、キーと値の型をセットで指定します。

def get_user_name(user: dict[str, str]) -> str:
    """
    ユーザー情報の辞書から、nameキーの値を取り出して返します。
    user は {"name": "Taro", "email": "[email protected]"} のような辞書を想定しています。
    """
    return user["name"]
Python
  • dict[str, str] → 「キーも値も文字列」の辞書
  • user["name"] が文字列であることを期待している

もう少し複雑な例も見てみましょう。

def get_price(product: dict[str, int]) -> int:
    """
    商品情報の辞書から、priceキーの値(整数)を取り出して返します。
    product は {"name": "Apple", "price": 120} のような辞書を想定しています。
    """
    return product["price"]
Python
  • dict[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
Python
  • a: 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)
Python
  • values: 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)
Python
  • key: str → キーは文字列
  • -> Optional[str] → 戻り値は「文字列かNone」

この関数を使う側は、 「Noneの可能性」を意識したコードになります。

value = get_config_value("SECRET_KEY")

if value is None:
    print("SECRET_KEY が設定されていません")
else:
    print(f"SECRET_KEY は {value} です")
Python

Day 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でこの感覚をつかんだことで、 これから書いていく関数は、

「ただ動くだけじゃなく、意図がはっきり伝わるもの」

へと、静かに変わっていきます。

型ヒントは、 未来の自分と仲間への、 ちいさな「思いやりのメモ」です。

少しずつ、でも確実に、 コードにそのメモを増やしていきましょう。

タイトルとURLをコピーしました