PEP 604 – X | Y로 유니언 타입 작성 허용
- Author:
- Philippe PRADOS <python at prados.fr>, Maggie Moss <maggiebmoss at gmail.com>
- Sponsor:
- Chris Angelico <rosuav at gmail.com>
- BDFL-Delegate:
- Guido van Rossum <guido at python.org>
- Discussions-To:
- Typing-SIG list
- Status:
- Final
- Type:
- Standards Track
- Topic:
- Typing
- Created:
- 28-Aug-2019
- Python-Version:
- 3.10
- Post-History:
- 28-Aug-2019, 05-Aug-2020
번역·라이선스 안내
이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판
초록
이 PEP는 Union[X, Y]를 X | Y로 작성할 수 있도록 타입에 | 연산자를 오버로딩하는 것을 제안하며, 이 표현이 isinstance와 issubclass 호출에 나타날 수 있도록 허용합니다.
동기
PEP 484와 PEP 526은 변수, 매개변수, 함수 반환값에 타입을 추가하는 일반적인 구문을 제안합니다. PEP 585는 제너릭에 매개변수를 런타임에 노출하는 것을 제안합니다. Mypy [1]는 다음과 같은 구문을 허용합니다:
annotation: name_type
name_type: NAME (args)?
args: '[' paramslist ']'
paramslist: annotation (',' annotation)* [',']
- 분리합(유니언 타입)을 나타내려면 사용자는
Union[X, Y]를 사용해야 합니다.
이 구문의 장황함은 타입 채택에 도움이 되지 않습니다.
제안
Scala [2]와 Pike [3]에서 영감을 받아, 이 제안은 type.__or__() 연산자를 추가합니다. 이 새로운 연산자를 사용하면 Union[int, str] 대신 int | str을 작성할 수 있습니다. 어노테이션뿐만 아니라, 이 표현식의 결과는 isinstance()와 issubclass()에서도 유효하게 됩니다:
isinstance(5, int | str)
issubclass(bool, int | float)
또한 Optional[t] 대신 t | None 또는 None | t를 작성할 수 있게 됩니다:
isinstance(None, int | None)
isinstance(42, None | int)
명세
새로운 유니언 구문은 함수, 변수, 매개변수 어노테이션에 대해 허용되어야 합니다.
단순화된 구문
# Instead of
# def f(list: List[Union[int, str]], param: Optional[int]) -> Union[float, str]
def f(list: List[int | str], param: int | None) -> float | str:
pass
f([1, "abc"], None)
# Instead of typing.List[typing.Union[str, int]]
typing.List[str | int]
list[str | int]
# Instead of typing.Dict[str, typing.Union[int, float]]
typing.Dict[str, int | float]
dict[str, int | float]
기존의 typing.Union과 | 구문은 동등해야 합니다.
int | str == typing.Union[int, str]
typing.Union[int, int] == int
int | int == int
유니언 내 항목의 순서는 동등성 비교에 영향을 주지 않아야 합니다.
(int | str) == (str | int)
(int | str | float) == typing.Union[str, float, int]
Optional 값은 새로운 유니언 구문과 동등해야 합니다
None | t == typing.Optional[t]
새로운 Union.__repr__() 메서드가 구현되어야 합니다.
str(int | list[str])
# int | list[str]
str(int | int)
# int
isinstance와 issubclass
유니언 항목이 isinstance와 issubclass 자체에 유효한 인자인 한, 새로운 구문은 isinstance와 issubclass 호출에 허용되어야 합니다.
# valid
isinstance("", int | str)
# invalid
isinstance(2, list[int]) # TypeError: isinstance() argument 2 cannot be a parameterized generic
isinstance(1, int | list[int])
# valid
issubclass(bool, int | float)
# invalid
issubclass(bool, bool | list[int])
호환되지 않는 변경 사항
일부 상황에서는 예상대로 예외가 발생하지 않을 수 있습니다.
메타클래스가 __or__ 연산자를 구현한 경우, 이것이 이를 오버라이드합니다:
>>> class M(type):
... def __or__(self, other): return "Hello"
...
>>> class C(metaclass=M): pass
...
>>> C | int
'Hello'
>>> int | C
typing.Union[int, __main__.C]
>>> Union[C, int]
typing.Union[__main__.C, int]
이의 및 답변
논의에 대한 더 자세한 내용은 아래 링크를 참조하십시오:
1. Union[type1, type2]를 위한 새로운 연산자를 추가할까요?
찬성:
- 이 구문은 더 읽기 쉬울 수 있으며, 다른 언어(Scala 등)와 유사합니다
- 런타임에
int|str은typing을 임포트해서 가져와야 하는 모든 것 대신 3.10에서 단순한 객체를 반환할 수 있습니다
단점:
- 이 연산자를 추가하면
typing과builtins사이에 의존성이 생깁니다 - 백포트를 깨뜨립니다(
typing은 쉽게 백포트할 수 있지만 핵심types는 그럴 수 없다는 점에서) - Python 자체를 바꿀 필요가 없더라도 mypy, Pyre, PyCharm, Pytype, 그리고 또 무엇이 있을지 모를 다른 도구들에서 여전히 이를 구현해야 합니다(사소한 변경입니다, “참조 구현”을 참조하십시오)
2. type1 | type2 구문을 받아들이도록 PEP 484(타입 힌트)만 변경할까요?
어노테이션의 동적 평가(eval())와 호환되지 않는 것을 받아들인다면, PEP 563(어노테이션의 평가 지연)만으로 이 제안을 수용하기에 충분합니다.
>>> from __future__ import annotations
>>> def foo() -> int | str: pass
...
>>> eval(foo.__annotations__['return'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
TypeError: unsupported operand type(s) for |: 'type' and 'type'
3. Union을 받아들이도록 isinstance()와 issubclass()를 확장할까요?
isinstance(x, str | int) ==> "is x an instance of str or int"
장점:
- 허용된다면 인스턴스 검사는 매우 깔끔해 보이는 표기법을 사용할 수 있을 것입니다
단점:
typing모듈 전체를builtin으로 이전해야 합니다
참조 구현
t1 | t2의 반환값을 담을 새로운 내장 Union 타입을 구현해야 하며, isinstance()와 issubclass()에서 이를 지원해야 합니다. 이 타입은 types 모듈에 둘 수 있습니다. types.Union과 typing.Union 사이의 상호운용성을 제공해야 합니다.
Python 언어가 확장되고 나면, mypy [1] 및 다른 타입 검사기들도 이 새로운 문법을 받아들이도록 업데이트되어야 합니다.
- cpython에 대한 제안된 구현은 여기에 있습니다.
- mypy에 대한 제안된 구현은 여기에 있습니다.
참고 자료
Copyright
This document is placed in the public domain or under the CC0-1.0-Universal license, whichever is more permissive.