Optional 型のヒントはどのように使用すればよいですか? 質問する

Optional 型のヒントはどのように使用すればよいですか? 質問する

型ヒントの使い方を理解しようとしています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[]NoneOptionalペップ604より優れた構文が導入されました。以下を参照してください。

したがって、2 つの例では、dictと のコンテナー タイプがありますが、キーワード引数listのデフォルト値では も許可されていることが示されているため、 を使用します。aNoneOptional[...]

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[]= NoneNoneUnion[...]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]NoneNone

補足: コードが Python 3.9 以降のみをサポートする必要がある場合を除き、標準ライブラリのコンテナ型を型ヒントで使用することは避けてください。コンテナ型にどのような型を含める必要があるかを指定できないためです。したがって、dictと の代わりに、それぞれと をlist使用してください。また、コンテナ型からのみ読み取る場合は、不変の抽象コンテナ型を受け入れることもできます。リストとタプルはオブジェクトですが、は型です。typing.Dicttyping.ListSequencedictMapping

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]]MappingSequence

Python 3.10では|、型ヒントにunion演算子が導入されました。ペップ604の代わりに とUnion[str, int]書くことができますstr | int。他の型ヒント言語と同様に、Python 3.10 以降では、オプションの引数を示す推奨される (より簡潔な) 方法は です。Type | Noneたとえば、str | Noneまたは ですlist | None

おすすめ記事