1. ホーム
  2. python

[解決済み] Optionalタイプのヒントはどのように使用すればよいですか?

2022-03-14 17:40:38

質問

を使用する方法を理解しようとしています。 Optional 型ヒントを表示します。から PEP-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[] ということです。

解決方法は?

Optional[...] は、以下の略記法です。 Union[..., None] で、特定の型のオブジェクトが必要であることを型チェッカに伝えます。 または None が必要です。 ... 任意の有効なタイプヒント 複雑な複合型を含む、または Union[] より多くの型の キーワード引数にデフォルト値の None を使用する必要があります。 Optional . (注意:Python 3.10 以降を対象としている場合。 PEP 604 はより良い構文を導入しました。)

つまり、この2つの例では dictlist コンテナタイプのデフォルト値は 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[] を追加するか、あるいは NoneUnion[] . そこで 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[] をエイリアスにすることで、より簡単になりました。 Optional[...] の代わりに使用されました。 Union[str, int, None] . その None の値は結局のところ「サブウィジェットID」ではなく、値の一部です。 None は、値がないことを示すためのものです。

補足:Python 3.9以降をサポートするコードでない限り、標準ライブラリのコンテナ型をタイプヒンティングに使うのは避けたいところです。ですから、代わりに dictlist を使用します。 typing.Dicttyping.List それぞれ また 読み コンテナ型から、任意の不変の抽象的なコンテナ型を受け入れるのと同じように、リストとタプルは Sequence オブジェクトであり、一方 dictMapping 型になります。

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 以降では、標準のコンテナ型はすべて更新され、タイプヒントでの使用をサポートしています。 PEP 585 . しかし 今、あなたは できる 使用 dict[str, int] または list[Union[int, str]] を使用することもできますが、より表現力の高い MappingSequence アノテーションは、関数が内容を変更しないこと (読み取り専用として扱われる) を示し、関数が 任意の オブジェクトが、それぞれマッピングやシーケンスとして動作します。

Python 3.10 で導入された | 演算子を型ヒンティングに組み込むことができます。 PEP 604 . の代わりに Union[str, int] と書くことができます。 str | int . 他の型暗示言語と同様に、Python 3.10 以降では、オプションの引数を表す好ましい(より簡潔な)方法は、現在 Type | None 例えば str | None または list | None .