nikkie-ftnextの日記

イベントレポートや読書メモを発信

PythonでOptional型の型ヒントは Optional[X] と X | None 、どちらがいいのでしょう?

今の私の結論を言うと、好みです。
Union[X, None] という3択目もありますが、好みだと思います。

はじめに

ミリシタの馬場このみさん1もよろしくね、nikkieです。

表題の件について、綴っていきます。
多少のただし書きを加えていますが、要は「好みです」としか書いていません
お急ぎの方は好きな書き方を使ってください。

目次

PythonでUnion型の型ヒント

Python 3.10で動きがありました。
https://docs.python.org/ja/3/whatsnew/3.10.html#pep-604-new-type-union-operator

日本語のオススメはこちら

しかし、PEP 604: Allow writing union types as X | Y では、Union を使わなくとも、typescriptなどと同じように | 演算子を使って指定できるようになりました。

「int型またはstr型」を表すUnion[int, str]は、int | str同じです。

https://docs.python.org/ja/3/library/typing.html#typing.Union

ユニオン型; Union[X, Y]X | Y と等価で X または Y を表します。

詳しいドキュメントはこちら:https://docs.python.org/ja/3/library/stdtypes.html#union-type

Optional型は、NoneとのUnion

https://docs.python.org/ja/3/library/typing.html#typing.Optional

Optional[X]X | None (や Union[X, None]) と同等です。

Python 3.10の変更により、Union[X, None](X型またはNone)をX | Noneと書けるようになったわけですね。

過去に記事も書いています

Optional型、どれで書く?

あなたの好みで書いてくださいね

PyCon JP 2021より

LTでアンケートがありました。

nikkieの見解

X | None派です。

この派閥に属すまでの経緯を書きます。

Python 3.9で組み込み型(listなど)が型ヒントに使えるようになりました。
私は最初「え、なんで?」と飲み込めなかったんですよ、typing.Listで型ヒントしてきたのに、それがdeprecateされてlistが望ましいといきなり言うだなんてあんまりだ!

PEPにあたっていくうちに、これは歓迎すべきという主張が理解できてきたんですね2
そもそもPythonの型ヒントはオプショナルとして、言語は変更せずtypingモジュールを外付けする形で始まっています。
それが、組み込み型を型ヒントに使うよう変更できるまでに、型ヒントが普及したんですよ!

この流れの先にUnion|で表せる変更もあるととらえています。
これも言語自体が型ヒントをサポート・拡張する深化であり、私は積極的に書いていきたい立場です。
Unionって打つより文字数が少ないですしね。

??「one obvious wayを志向するPythonなのに、Optional型の型ヒントは複数あるんですか?」

Zen of Pythonをご存知なのですね。

There should be one-- and preferably only one --obvious way to do it.

あいたたた。
そうなんですよ、Pythonなのにやり方が1つじゃないんですよ

メーリングリストの議論を追う

PEP3からメーリングリストに飛べます。

※膨大な分量があり、全部精読はできていません

Guido氏

はっとする投稿がありました。
ここから「やり方は1つじゃないんですね」という指摘は当たらないかもなあと感じています。
とらえ方が変わった投稿です。

https://mail.python.org/archives/list/python-ideas@python.org/message/2PO6ODO2WZXPDSZGI7BKJAY5NT5WQMVW/

Optionalって要るんですか?Union[T, None]だけでいいのではないでしょうか?」に、Guido氏が反対を示しています。

Guido氏の主張に表れているのは、人間にとっての読みやすさ4(理解しやすさ)だと思います

Every time I see Union[T, None] I have to read it carefully to see what it means.
When I see Optional[T] my brain moves on immediately

  • Union[T, None]は都度注意深く読まなければならない
  • Optional[T]はただちに理解できる

意味内容が同じであっても、理解しやすさには違いがある
Optional型の型ヒントは何通りも書けますが、全く同じやり方が重複しているわけではないと気づきました。
その点で、「Union[T, None]Optional[T]」と複数通りありますが、これはやり方が1つでないとは言えないという立場です。

ちなみに??さんは私の心の中に住んでいます。

上でどちらを選ぶかは好みと書きましたが、開発チームの状況も1つの変数だと思います。
ある状況ではOptional[T]に揃えた方がいいかもしれず、別の状況ではT | Noneの方がいいかもしれません(そんなの決めない!がうまくいくケースもあるかも)。
なので、あなただけの好みだけでなく、一緒に開発する人の好みにも注意を払って決めてはいかがでしょうか。

余談:Inadaさんの指摘

日本人コミッターの稲田さんは否定的な立場でした。
その中で気になったのがこちら

https://mail.python.org/archives/list/python-ideas@python.org/message/3PJKNQ64J3XCEJUC5G26X4TTJH7WXRM6/

"there is new way to do it but it may be much slower and use much memory, so you shouldn't use it unless you can ignore performance."

話の流れとしては

  • int | strのように書けたら、見た目がよいのでみんな使うだろう
  • ただしパフォーマンスは劣る書き方を推奨される形になる

この状況への懸念を稲田さんは表明しているという理解です。
|のパフォーマンスについて宿題事項に積まれました(ガンガン使っていきたいけど、懸念があるの?)

終わりに

PythonでOptional型の型ヒントについて書きました。
Pythonという言語が進化してきているため、Optional[X]X | NoneUnion[X, None]と3択があります。

私は好みで使えばよいという立場です。
私自身はX | None派です。型ヒントの普及に思いを馳せながら日々書いています。
今回Guido氏の投稿で気づかされたように、Optional[X]は明確に分かりやすい書き方であり、開発チームの状況によってどれを推奨するかは変わると思います(揃えないという選択肢も含めて)。


  1. 今日もナイスセクシー! Act-4の dear... よかった...
  2. それを話したスライドがこちらです:https://docs.google.com/presentation/d/1KJlSSS-ZDByqqg_HO0_EFGbXCBqR8OMzzWwz8xvGQkU/edit#slide=id.gac886c4914_0_51
  3. https://peps.python.org/pep-0604/#objections-and-responses
  4. Pythonに通底している思想だと思います