[python] 선택적 유형 힌트는 어떻게 사용해야합니까?

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[]NoneOptional

따라서 두 예의 경우 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[](A)에 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[]했기 때문에을 별칭으로 이동하는 리팩터링 이 훨씬 쉬워졌습니다 . 값은 값의 일부가 아니다, 모든 후 ‘는 SubWidget ID’아닌 플래그 값의 부재를 의미한다.Optional[...]Union[str, int, None]NoneNone

참고 : 코드가 Python 3.9 이상 만 지원해야하는 경우가 아니면 포함해야하는 유형에 대해 아무 것도 말할 수 없으므로 유형 힌팅에서 표준 라이브러리 컨테이너 유형을 사용하지 않는 것이 좋습니다. 그래서 대신 dict하고 list, 사용 typing.Dicttyping.List각각. 컨테이너 유형 에서만 읽을 때 변경 불가능한 추상 컨테이너 유형을 허용 할 수 있습니다. 목록과 튜플는 Sequence동안, 객체 dictA는 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 이상에서 표준 컨테이너 유형은 모두 유형 힌트에서 사용할 수 있도록 업데이트되었습니다 . PEP 585를 참조하세요 . 그러나 지금 동안, 사용 dict[str, int]하거나 list[Union[int, str]], 당신은 여전히 더 많은 표현 사용할 수 있습니다 MappingSequence(그들은 ‘읽기 전용’으로 처리됩니다), 그리고 기능이 작동 것이라고 함수 내용을 변이되지 않음을 나타 내기 위해 주석을 각각 매핑 또는 시퀀스로 작동하는 모든 개체.


답변

mypy 타이핑 모듈 문서 에서 직접 .

  • “Optional [str]은 Union [str, None]의 약자 또는 별칭입니다. 기능 서명을 좀 더 깔끔하게 보이게하기위한 편의상 대부분 존재합니다.”


답변