Pythonの型の紹介¶
Python 3.6以降 では「型ヒント」オプションがサポートされています。
これらの "型ヒント" は変数の型を宣言することができる新しい構文です。(Python 3.6以降)
変数に型を宣言することでエディターやツールがより良いサポートを提供することができます。
ここでは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_name
とlast_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_uppercase
?またはcapitalize
?
そして、古くからプログラマーの友人であるエディタで自動補完を試してみます。
関数の最初のパラメータ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
エディタは変数の型を知っているので、補完だけでなく、エラーチェックをすることもできます。
これでage
をstr(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_d, item_e
型パラメータを持つジェネリック型¶
データ構造の中には、dict
、list
、set
、そしてtuple
のように他の値を含むことができるものがあります。また内部の値も独自の型を持つことができます。
これらの型や内部の型を宣言するには、Pythonの標準モジュールtyping
を使用します。
これらの型ヒントをサポートするために特別に存在しています。
List
¶
例えば、str
のlist
の変数を定義してみましょう。
typing
からList
をインポートします(大文字のL
を含む):
from typing import List
def process_items(items: List[str]):
for item in items:
print(item)
🤓 Other versions and variants
def process_items(items: list[str]):
for item in items:
print(item)
同じようにコロン(:
)の構文で変数を宣言します。
型として、List
を入力します。
リストはいくつかの内部の型を含む型なので、それらを角括弧で囲んでいます。
from typing import List
def process_items(items: List[str]):
for item in items:
print(item)
🤓 Other versions and variants
def process_items(items: list[str]):
for item in items:
print(item)
豆知識
角括弧内の内部の型は「型パラメータ」と呼ばれています。
この場合、str
はList
に渡される型パラメータです。
つまり: 変数items
はlist
であり、このリストの各項目はstr
です。
そうすることで、エディタはリストの項目を処理している間にもサポートを提供できます。
タイプがなければ、それはほぼ不可能です。
変数item
はリストitems
の要素の一つであることに注意してください。
それでも、エディタはそれがstr
であることを知っていて、そのためのサポートを提供しています。
Tuple
と Set
¶
tuple
とset
の宣言も同様です:
from typing import Set, Tuple
def process_items(items_t: Tuple[int, int, str], items_s: Set[bytes]):
return items_t, items_s
🤓 Other versions and variants
def process_items(items_t: tuple[int, int, str], items_s: set[bytes]):
return items_t, items_s
つまり:
-
変数
items_t
はint
、int
、str
の3つの項目を持つtuple
です -
変数
items_s
はそれぞれの項目がbytes
型であるset
です。
Dict
¶
dict
を宣言するためには、カンマ区切りで2つの型パラメータを渡します。
最初の型パラメータはdict
のキーです。
2番目の型パラメータはdict
の値です。
from typing import Dict
def process_items(prices: Dict[str, float]):
for item_name, item_price in prices.items():
print(item_name)
print(item_price)
🤓 Other versions and variants
def process_items(prices: dict[str, float]):
for item_name, item_price in prices.items():
print(item_name)
print(item_price)
つまり:
- 変数
prices
はdict
であり:- この
dict
のキーはstr
型です。(つまり、各項目の名前) - この
dict
の値はfloat
型です。(つまり、各項目の価格)
- この
Optional
¶
また、Optional
を使用して、変数がstr
のような型を持つことを宣言することもできますが、それは「オプション」であり、None
にすることもできます。
from typing import Optional
def say_hi(name: Optional[str] = None):
if name is not None:
print(f"Hey {name}!")
else:
print("Hello World")
ただのstr
の代わりにOptional[str]
を使用することで、エディタは値が常にstr
であると仮定している場合に実際にはNone
である可能性があるエラーを検出するのに役立ちます。
ジェネリック型¶
以下のように角括弧で型パラメータを取る型を:
List
Tuple
Set
Dict
Optional
- ...など
ジェネリック型 または ジェネリクス と呼びます。
型としてのクラス¶
変数の型としてクラスを宣言することもできます。
例えば、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
そして、再び、すべてのエディタのサポートを得ることができます:
Pydanticのモデル¶
Pydantic はデータ検証を行うためのPythonライブラリです。
データの「形」を属性付きのクラスとして宣言します。
そして、それぞれの属性は型を持ちます。
さらに、いくつかの値を持つクラスのインスタンスを作成すると、その値を検証し、適切な型に変換して(もしそうであれば)全てのデータを持つオブジェクトを提供してくれます。
また、その結果のオブジェクトですべてのエディタのサポートを受けることができます。
Pydanticの公式ドキュメントから引用:
from datetime import datetime
from typing import List, Union
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = "John Doe"
signup_ts: Union[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
🤓 Other versions and variants
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
from datetime import datetime
from typing import Union
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = "John Doe"
signup_ts: Union[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
情報
Pydanticについてより学びたい方はドキュメントを参照してください.
FastAPI はすべてPydanticをベースにしています。
すべてのことはチュートリアル - ユーザーガイドで実際に見ることができます。
FastAPIでの型ヒント¶
FastAPI はこれらの型ヒントを利用していくつかのことを行います。
FastAPI では型ヒントを使って型パラメータを宣言すると以下のものが得られます:
- エディタサポート.
- 型チェック.
...そして FastAPI は同じように宣言をすると、以下のことを行います:
- 要件の定義: リクエストパスパラメータ、クエリパラメータ、ヘッダー、ボディ、依存関係などから要件を定義します。
- データの変換: リクエストのデータを必要な型に変換します。
- データの検証: リクエストごとに:
- データが無効な場合にクライアントに返される 自動エラー を生成します。
- ドキュメント OpenAPIを使用したAPI:
- 自動的に対話型ドキュメントのユーザーインターフェイスで使用されます。
すべてが抽象的に聞こえるかもしれません。心配しないでください。 この全ての動作は チュートリアル - ユーザーガイドで見ることができます。
重要なのは、Pythonの標準的な型を使うことで、(クラスやデコレータなどを追加するのではなく)1つの場所で FastAPI が多くの作業を代わりにやってくれているということです。
情報
すでにすべてのチュートリアルを終えて、型についての詳細を見るためにこのページに戻ってきた場合は、mypy
のチートシートを参照してください