コンテンツにスキップ

Pythonの型の紹介

🌐 AI と人間による翻訳

この翻訳は、人間のガイドに基づいて AI によって作成されました。🤝

原文の意図を取り違えていたり、不自然な表現になっている可能性があります。🤖

AI LLM をより適切に誘導するのを手伝う ことで、この翻訳を改善できます。

英語版

Python にはオプションの「型ヒント」(「型アノテーション」とも呼ばれます)がサポートされています。

これらの 「型ヒント」 やアノテーションは、変数のを宣言できる特別な構文です。

変数に型を宣言することで、エディターやツールがより良いサポートを提供できます。

これは Python の型ヒントについての クイックチュートリアル/リフレッシュ にすぎません。FastAPI で使うために必要な最低限のことだけをカバーしています。...実際には本当に少ないです。

FastAPI はすべてこれらの型ヒントに基づいており、多くの強みと利点を与えてくれます。

しかし、たとえ FastAPI をまったく使用しない場合でも、それらについて少し学ぶことで利点を得られます。

備考

もしあなたが Python の専門家で、すでに型ヒントについてすべて知っているのであれば、次の章まで読み飛ばしてください。

動機

簡単な例から始めてみましょう:

def get_full_name(first_name, last_name):
    full_name = first_name.title() + " " + last_name.title()
    return full_name


print(get_full_name("john", "doe"))

このプログラムを呼び出すと、以下が出力されます:

John Doe

この関数は以下のようなことを行います:

  • first_namelast_name を取得します。
  • title() を用いて、それぞれの最初の文字を大文字に変換します。
  • 真ん中にスペースを入れて連結します。
def get_full_name(first_name, last_name):
    full_name = first_name.title() + " " + last_name.title()
    return full_name


print(get_full_name("john", "doe"))

編集

これはとても簡単なプログラムです。

しかし、今、あなたがそれを一から書いていたと想像してみてください。

パラメータの準備ができていたら、そのとき、関数の定義を始めていたことでしょう...

しかし、そうすると「最初の文字を大文字に変換するあのメソッド」を呼び出す必要があります。

それは upper でしたか?uppercase でしたか?first_uppercasecapitalize

そして、古くからプログラマーの友人であるエディタで自動補完を試してみます。

関数の最初のパラメータ first_name を入力し、ドット(.)を入力してから、Ctrl+Space を押すと補完が実行されます。

しかし、悲しいことに、これはなんの役にも立ちません:

型の追加

先ほどのコードから一行変更してみましょう。

関数のパラメータである次の断片を、以下から:

    first_name, last_name

以下へ変更します:

    first_name: str, last_name: str

これだけです。

それが「型ヒント」です:

def get_full_name(first_name: str, last_name: str):
    full_name = first_name.title() + " " + last_name.title()
    return full_name


print(get_full_name("john", "doe"))

これは、以下のようにデフォルト値を宣言するのと同じではありません:

    first_name="john", last_name="doe"

それとは別物です。

イコール(=)ではなく、コロン(:)を使用します。

そして、通常、型ヒントを追加しても、それらがない状態と起こることは何も変わりません。

しかし今、あなたが再びその関数を作成している最中に、型ヒントを使っていると想像してみてください。

同じタイミングで Ctrl+Space で自動補完を実行すると、以下のようになります:

これであれば、あなたは「ベルを鳴らす」ものを見つけるまで、オプションを見てスクロールできます:

より強い動機

この関数を見てください。すでに型ヒントを持っています:

def get_name_with_age(name: str, age: int):
    name_with_age = name + " is this old: " + age
    return name_with_age

エディタは変数の型を知っているので、補完だけでなく、エラーチェックをすることもできます:

これで agestr(age) で文字列に変換して修正する必要があることがわかります:

def get_name_with_age(name: str, age: int):
    name_with_age = name + " is this old: " + str(age)
    return name_with_age

型の宣言

型ヒントを宣言する主な場所を見てきました。関数のパラメータです。

これは FastAPI で使用する主な場所でもあります。

単純な型

str だけでなく、Python の標準的な型すべてを宣言できます。

例えば、以下を使用可能です:

  • int
  • float
  • bool
  • bytes
def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes):
    return item_a, item_b, item_c, item_d, item_e
🤓 Other versions and variants
def get_items(item_a: str, item_b: int, item_c: float, item_d: bool, item_e: bytes):
    return item_a, item_b, item_c, item_d, item_e

typing モジュール

いくつかの追加のユースケースでは、標準ライブラリの typing モジュールから何かをインポートする必要があるかもしれません。例えば「任意の型」を受け付けることを宣言したい場合、typingAny を使えます:

from typing import Any


def some_function(data: Any):
    print(data)

ジェネリック型

一部の型は、角括弧内で「型パラメータ」を受け取り、内部の型を定義できます。例えば「文字列のリスト」は list[str] として宣言します。

このように型パラメータを取れる型は Generic types(ジェネリクス)と呼ばれます。

次の組み込み型をジェネリクスとして(角括弧と内部の型で)使えます:

  • list
  • tuple
  • set
  • dict

List

例えば、strlist の変数を定義してみましょう。

同じコロン(:)の構文で変数を宣言します。

型として、list を指定します。

リストはいくつかの内部の型を含む型なので、それらを角括弧で囲みます:

def process_items(items: list[str]):
    for item in items:
        print(item)

情報

角括弧内の内部の型は「型パラメータ」と呼ばれています。

この場合、strlist に渡される型パラメータです。

つまり: 変数 itemslist であり、このリストの各項目は str です。

そうすることで、エディタはリストの項目を処理している間にもサポートを提供できます。

型がなければ、それはほぼ不可能です。

変数 item はリスト items の要素の一つであることに注意してください。

それでも、エディタはそれが str であることを知っていて、そのためのサポートを提供しています。

Tuple と Set

tupleset の宣言も同様です:

def process_items(items_t: tuple[int, int, str], items_s: set[bytes]):
    return items_t, items_s

つまり:

  • 変数 items_tint、別の intstr の 3 つの項目を持つ tuple です。
  • 変数 items_sset であり、その各項目は bytes 型です。

Dict

dict を定義するには、カンマ区切りで 2 つの型パラメータを渡します。

最初の型パラメータは dict のキーです。

2 番目の型パラメータは dict の値です:

def process_items(prices: dict[str, float]):
    for item_name, item_price in prices.items():
        print(item_name)
        print(item_price)

つまり:

  • 変数 pricesdict です:
    • この dict のキーは str 型です(例えば、各項目の名前)。
    • この dict の値は float 型です(例えば、各項目の価格)。

Union

変数が 複数の型のいずれか になり得ることを宣言できます。例えば、int または str です。

それを定義するには、両方の型を区切るために 縦棒(| を使います。

これは「ユニオン(union)」と呼ばれます。変数がそれら 2 つの型の集合の和集合のいずれかになり得るからです。

def process_item(item: int | str):
    print(item)

これは itemint または str になり得ることを意味します.

None の可能性

値が str のような型を持つ可能性がある一方で、None にもなり得ることを宣言できます。

def say_hi(name: str | None = None):
    if name is not None:
        print(f"Hey {name}!")
    else:
        print("Hello World")

ただの str の代わりに str | None を使用することで、値が常に str であると仮定しているときに、実際には None である可能性もあるというエラーをエディタが検出するのに役立ちます。

型としてのクラス

変数の型としてクラスを宣言することもできます。

名前を持つ Person クラスがあるとしましょう:

class Person:
    def __init__(self, name: str):
        self.name = name


def get_person_name(one_person: Person):
    return one_person.name

変数を Person 型として宣言できます:

class Person:
    def __init__(self, name: str):
        self.name = name


def get_person_name(one_person: Person):
    return one_person.name

そして、再び、すべてのエディタのサポートを得ることができます:

これは「one_person はクラス Personインスタンス である」ことを意味します。

one_personPerson という名前の クラス である」という意味ではありません。

Pydantic のモデル

Pydantic はデータ検証を行うための Python ライブラリです。

データの「形」を属性付きのクラスとして宣言します。

そして、それぞれの属性は型を持ちます。

さらに、いくつかの値を持つクラスのインスタンスを作成すると、その値を検証し、適切な型に変換して(もしそうであれば)すべてのデータを持つオブジェクトを提供してくれます。

また、その結果のオブジェクトですべてのエディタのサポートを受けることができます。

Pydantic の公式ドキュメントからの例:

from datetime import datetime

from pydantic import BaseModel


class User(BaseModel):
    id: int
    name: str = "John Doe"
    signup_ts: datetime | None = None
    friends: list[int] = []


external_data = {
    "id": "123",
    "signup_ts": "2017-06-01 12:22",
    "friends": [1, "2", b"3"],
}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123

FastAPI はすべて Pydantic をベースにしています。

すべてのことは チュートリアル - ユーザーガイド で実際に見ることができます。

メタデータアノテーション付き型ヒント

Python には、Annotated を使って型ヒントに 追加の メタデータ を付与できる機能もあります。

Annotatedtyping からインポートできます。

from typing import Annotated


def say_hello(name: Annotated[str, "this is just metadata"]) -> str:
    return f"Hello {name}"

Python 自体は、この Annotated で何かをするわけではありません。また、エディタや他のツールにとっても、型は依然として str です。

しかし、Annotated 内のこのスペースを使って、アプリケーションをどのように動作させたいかについての追加メタデータを FastAPI に提供できます。

覚えておくべき重要な点は、Annotated に渡す 最初の「型パラメータ」実際の型 であることです。残りは、他のツール向けのメタデータにすぎません。

今のところは、Annotated が存在し、それが標準の Python であることを知っておけば十分です。😎

後で、これがどれほど 強力 になり得るかを見ることになります。

豆知識

これが 標準の Python であるという事実は、エディタで、使用しているツール(コードの解析やリファクタリングなど)とともに、可能な限り最高の開発体験 が得られることを意味します。 ✨

また、あなたのコードが他の多くの Python ツールやライブラリとも非常に互換性が高いことも意味します。 🚀

FastAPI での型ヒント

FastAPI はこれらの型ヒントを利用していくつかのことを行います。

FastAPI では型ヒントを使ってパラメータを宣言すると以下のものが得られます:

  • エディタサポート
  • 型チェック

...そして FastAPI は同じ宣言を使って、以下のことを行います:

  • 要件の定義: リクエストのパスパラメータ、クエリパラメータ、ヘッダー、ボディ、依存関係などから要件を定義します。
  • データの変換: リクエストから必要な型にデータを変換します。
  • データの検証: 各リクエストから来るデータについて:
    • データが無効な場合にクライアントに返される 自動エラー を生成します。
  • OpenAPI を使用して API を ドキュメント化 します:
    • これは自動の対話型ドキュメントのユーザーインターフェイスで使われます。

すべてが抽象的に聞こえるかもしれません。心配しないでください。 この全ての動作は チュートリアル - ユーザーガイド で見ることができます。

重要なのは、Python の標準的な型を使うことで、(クラスやデコレータなどを追加するのではなく)1 つの場所で FastAPI が多くの作業を代わりにやってくれているということです。

情報

すでにすべてのチュートリアルを終えて、型についての詳細を見るためにこのページに戻ってきた場合は、良いリソースとして mypy の「チートシート」 があります。