PythonのLiteral型について調べる過程で学んだことを記録。
そのため今回はtype文を中心に書きます。
今回の検証環境は以下の通りです。
- Python 3.12.1
- mypy 1.10.1
type文とは
type文はPython3.12から追加された型エイリアスを定義するための構文です。
英語だと、type statement
と表現するようです。
PEP695で提案されたようでした。
これまでの型エイリアスの定義方法
これまで、型エイリアスを定義する方法は2つありました。
- 代入によって作成する方法
- TypeAliasでマークする方法
代入によって作成する方法
区切り文字を表す、Delimiter
という型エイリアスを定義する例を書きます。
Literal
を利用してDelimiter
は,
か:
を許可するようにしています。
from typing import Literal Delimiter = Literal[",", ":"]
TypeAliasでマークする方法
from typing import Literal, TypeAlias Delimiter: TypeAlias = Literal[",", ":"]
type文を利用した定義方法
type文では先頭にtype
と記載するのみです。
from typing import Literal type Delimiter = Literal[",", ":"]
これまでのコードを見てみると、ちょっとした違いはあれど大きな違いはないと感じました。
実際に動かしてみる
例えば以下の引数delimiter: Delimiter
を第2引数に期待する関数を定義して、意図する値・意図しない値で呼び出してみます。
関数定義
def split_text(text: str, delimiter: Delimiter) -> None: pass
上記のsplit_text
を呼び出した場合の値
# OK例1 split_text("a,b,c", ",") # OK例2 split_text("a:b:c", ":") # NG例 # mypy側で以下のエラーが出る # error: Argument 2 to "split_text" has incompatible type "Literal['|']"; expected "Literal[',', ':']" [arg-type] split_text("a|b|c", "|")
実際に使用する場合の注意点
執筆時の最新のmypyバージョン 1.10.1 ではまだtype文は未対応のようでした。
そのためtype
文を利用すると、error: PEP 695 type aliases are not yet supported [valid-type]
と表示されます。
エラーを許容はしにくいと思うので、現状では代入かTypeAliasで定義することになりますが、TypeAliasはPython3.12でtype文導入に伴い、非推奨となったようでした。
typing.TypeAlias に記載があります。
以上からmypyの現状も鑑みると代入を利用するのが良さそうに思っています。
自分が動かしてみた時にエラーが出てStack overflowにも同様の質問がされており、知りました。毎度思いますが、最初にこうやってオープンな場で質問してくれる人、本当にありがたい・・・
Mypy error: PEP 695 type aliases are not yet supported
Pythonの型ヒント周りは割とバージョンによって変わることが多いので、これからも新バージョンが出た際には精力的にキャッチアップが必要だなと感じました。