Following system colour scheme Selected dark colour scheme Selected light colour scheme

Python 개선 제안 한국어 번역

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

Table of Contents

번역·라이선스 안내

이 비공식 한국어 번역은 원문 Copyright 절의 Public Domain or CC0-1.0, whichever is more permissive 조건에 따라 제공합니다. 원저자와 공식 원문은 그대로 표시합니다. 수정되지 않은 기준 원문 · 공식 최신판

Important

This PEP is a historical document. The up-to-date, canonical documentation can now be found at Union Type.

×

See PEP 1 for how to propose changes.

초록

이 PEP는 Union[X, Y]X | Y로 작성할 수 있도록 타입에 | 연산자를 오버로딩하는 것을 제안하며, 이 표현이 isinstanceissubclass 호출에 나타날 수 있도록 허용합니다.

동기

PEP 484PEP 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

유니언 항목이 isinstanceissubclass 자체에 유효한 인자인 한, 새로운 구문은 isinstanceissubclass 호출에 허용되어야 합니다.

# 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|strtyping을 임포트해서 가져와야 하는 모든 것 대신 3.10에서 단순한 객체를 반환할 수 있습니다

단점:

  • 이 연산자를 추가하면 typingbuiltins 사이에 의존성이 생깁니다
  • 백포트를 깨뜨립니다(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.Uniontyping.Union 사이의 상호운용성을 제공해야 합니다.

Python 언어가 확장되고 나면, mypy [1] 및 다른 타입 검사기들도 이 새로운 문법을 받아들이도록 업데이트되어야 합니다.

참고 자료