型ヒントの使い方を理解しようとしていますOptional
。ペップ484、またはのどちらにもOptional
を使用できることはわかっています。def test(a: int = None)
def test(a: Union[int, None])
def test(a: Optional[int])
しかし、次の例はどうでしょうか?
def test(a : dict = None):
#print(a) ==> {'a': 1234}
#or
#print(a) ==> None
def test(a : list = None):
#print(a) ==> [1,2,3,4, 'a', 'b']
#or
#print(a) ==> None
Optional[type]
は と同じ意味のようですがUnion[type, None]
、なぜ を使用する必要があるOptional[]
のでしょうか?
ベストアンサー1
Optional[...]
は の省略記法でUnion[..., None]
、型チェッカーに特定の型のオブジェクトが必要であるか、 が必要であるかを伝えます None
。は、複雑な複合型や 2 つ以上の型の を含む、有効な型ヒント...
を表します。デフォルト値 を持つキーワード引数がある場合は、 を使用する必要があります。(注: Python 3.10 以降を対象としている場合は、Union[]
None
Optional
ペップ604より優れた構文が導入されました。以下を参照してください。
したがって、2 つの例では、dict
と のコンテナー タイプがありますが、キーワード引数list
のデフォルト値では も許可されていることが示されているため、 を使用します。a
None
Optional[...]
from typing import Optional
def test(a: Optional[dict] = None) -> None:
#print(a) ==> {'a': 1234}
#or
#print(a) ==> None
def test(a: Optional[list] = None) -> None:
#print(a) ==> [1, 2, 3, 4, 'a', 'b']
#or
#print(a) ==> None
Optional[]
で を使用することUnion[]
と、 に を追加することNone
の間には技術的に違いはありませんUnion[]
。したがってOptional[Union[str, int]]
、 と はUnion[str, int, None]
まったく同じものです。
個人的には、デフォルト値を設定するために使用するキーワード引数の型を設定するときは常に を使用します。これにより、それが許可される理由がよりわかりやすくなります。さらに、これにより、その部分を別の型エイリアスに移動したり、引数が必須になった場合に後でその部分を削除したりすることが容易になります。Optional[]
= None
None
Union[...]
Optional[...]
例えば、
from typing import Optional, Union
def api_function(optional_argument: Optional[Union[str, int]] = None) -> None:
"""Frob the fooznar.
If optional_argument is given, it must be an id of the fooznar subwidget
to filter on. The id should be a string, or for backwards compatibility,
an integer is also accepted.
"""
Union[str, int]
次に、を型エイリアスに取り出すことでドキュメントが改善されます。
from typing import Optional, Union
# subwidget ids used to be integers, now they are strings. Support both.
SubWidgetId = Union[str, int]
def api_function(optional_argument: Optional[SubWidgetId] = None) -> None:
"""Frob the fooznar.
If optional_argument is given, it must be an id of the fooznar subwidget
to filter on. The id should be a string, or for backwards compatibility,
an integer is also accepted.
"""
をエイリアスに移動するリファクタリングは、の代わりに が使用されるUnion[]
ため、非常に簡単になりました。値は結局のところ「サブウィジェット ID」ではなく、値の一部ではなく、値が存在しないことを示すためのものです。Optional[...]
Union[str, int, None]
None
None
補足: コードが Python 3.9 以降のみをサポートする必要がある場合を除き、標準ライブラリのコンテナ型を型ヒントで使用することは避けてください。コンテナ型にどのような型を含める必要があるかを指定できないためです。したがって、dict
と の代わりに、それぞれと をlist
使用してください。また、コンテナ型からのみ読み取る場合は、不変の抽象コンテナ型を受け入れることもできます。リストとタプルはオブジェクトですが、は型です。typing.Dict
typing.List
Sequence
dict
Mapping
from typing import Mapping, Optional, Sequence, Union
def test(a: Optional[Mapping[str, int]] = None) -> None:
"""accepts an optional map with string keys and integer values"""
# print(a) ==> {'a': 1234}
# or
# print(a) ==> None
def test(a: Optional[Sequence[Union[int, str]]] = None) -> None:
"""accepts an optional sequence of integers and strings
# print(a) ==> [1, 2, 3, 4, 'a', 'b']
# or
# print(a) ==> None
Python 3.9以降では、標準コンテナ型はすべて更新され、型ヒントでの使用がサポートされています。ペップ585ただし、またはを使用できるようになりましたが、関数がコンテンツを変更しない (「読み取り専用」として扱われる) こと、および関数がそれぞれマッピングまたはシーケンスとして機能する任意のオブジェクトで機能することを示すために、より表現力豊かな および アノテーションを使用する必要がある場合もあります。dict[str, int]
list[Union[int, str]]
Mapping
Sequence
Python 3.10では|
、型ヒントにunion演算子が導入されました。ペップ604の代わりに とUnion[str, int]
書くことができますstr | int
。他の型ヒント言語と同様に、Python 3.10 以降では、オプションの引数を示す推奨される (より簡潔な) 方法は です。Type | None
たとえば、str | None
または ですlist | None
。