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
따라서 두 예의 경우 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[]
(A)에 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[]
했기 때문에을 별칭으로 이동하는 리팩터링 이 훨씬 쉬워졌습니다 . 값은 값의 일부가 아니다, 모든 후 ‘는 SubWidget ID’아닌 플래그 값의 부재를 의미한다.Optional[...]
Union[str, int, None]
None
None
참고 : 코드가 Python 3.9 이상 만 지원해야하는 경우가 아니면 포함해야하는 유형에 대해 아무 것도 말할 수 없으므로 유형 힌팅에서 표준 라이브러리 컨테이너 유형을 사용하지 않는 것이 좋습니다. 그래서 대신 dict
하고 list
, 사용 typing.Dict
및 typing.List
각각. 컨테이너 유형 에서만 읽을 때 변경 불가능한 추상 컨테이너 유형을 허용 할 수 있습니다. 목록과 튜플는 Sequence
동안, 객체 dict
A는 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]]
, 당신은 여전히 더 많은 표현 사용할 수 있습니다 Mapping
및 Sequence
(그들은 ‘읽기 전용’으로 처리됩니다), 그리고 기능이 작동 것이라고 함수 내용을 변이되지 않음을 나타 내기 위해 주석을 각각 매핑 또는 시퀀스로 작동하는 모든 개체.
답변
mypy 타이핑 모듈 문서 에서 직접 .
- “Optional [str]은 Union [str, None]의 약자 또는 별칭입니다. 기능 서명을 좀 더 깔끔하게 보이게하기위한 편의상 대부분 존재합니다.”