파이썬의 typing 내장 모듈로 타입 표시하기
타입 힌트(type hint)를 언어 차원에서 지원하기 위해서 파이썬 버전 3.5에서 typing
모듈이 표준 라이브러리에 추가되었습니다.
이번 포스팅에서는 typing
모듈을 사용해서 파이썬 코드에 타입 어노테이션을 추가하는 방법에 대해서 알아보겠습니다.
파이썬의 타입 어노테이션에 대한 자세한 설명은 관련 포스팅를 참고 바랍니다.
List, Dict, Tuple, Set
타입 어노테이션을 사용하다 보면 리스트, 사전, 튜플, 세트와 같은 파이썬에 내장된 자료구조에 대한 타입을 명시해야 할 때가 있습니다.
이때 그냥, list
, dict
, tuple
, set
와 같은 내장 타입을 이용할 수도 있지만, typing
모듈에서 제공하는 List
, Dict
, Tuple
, Set
를 사용하면 원소의 타입까지 명시해줄 수 있습니다.
from typing import List
nums: List[int] = [1, 2, 3]
from typing import Dict
temperatures: Dict[str, float] = {"bedroom": 25.1, "kitchen": 23, "bathroom": 19.8}
from typing import Tuple
user: Tuple[int, str, bool] = (3, "Dale", True)
from typing import Set
chars: Set[str] = {"A", "B", "C"}
Python 3.9 업데이트
Python 3.9에서 타입 어노테이션의 사용성이 대폭 개선이 되었습니다.
이제 typing
모듈에서 List
, Dict
, Tuple
, Set
를 불러오지 않고, list
, dict
, tuple
, set
내장 타입을 통해 바로 원소의 타입까지 명시해줄 수 있습니다. 🎊
nums: list[int] = [1, 2, 3]
temperatures: dict[str, float] = {"bedroom": 25.1, "kitchen": 23, "bathroom": 19.8}
user: tuple[int, str, bool] = (3, "Dale", True)
chars: set[str] = {"A", "B", "C"}
Final
재할당이 불가능한 변수, 즉 상수에 대한 타입 어노테이션을 추가할 때는 typing
모듈의 Final
을 사용합니다.
from typing import Final
TIME_OUT: Final[int] = 10
Union
여러 개의 타입이 허용될 수 있는 상황에서는 typing
모듈의 Union
을 사용할 수 있습니다.
from typing import Union
def toString(num: Union[int, float]) -> str:
return str(num)
>>> toString(1)
'1'
>>> toString(1.5)
'1.5'
Python 3.10 업데이트
Python 3.10에서는 |
연산자로 typing
모듈의 Union
을 대체할 수 있게 되었습니다.
따라서 위 코드는 다음과 같이 간소화할 수 있습니다. 🎉
def toString(num: int | float) -> str:
return str(num)
Optional
typing
모듈의 Optional
은 None
이 허용되는 함수의 매개 변수에 대한 타입을 명시할 때 유용합니다.
from typing import List, Optional
def repeat(message: str, times: Optional[int] = None) -> List[str]:
if times:
return [message] * times
else:
return [message]
위 예제에서, Optional[int]
는 Union[int, None]
과 동일한 효력을 갖습니다.
>>> repeat("Hi", 3)
['Hi', 'Hi', 'Hi']
>>> repeat("Hi")
['Hi', 'Hi', 'Hi']
Callable
파이썬에서는 함수를 일반 값처럼 변수에 저장하거나 함수의 인자로 넘기거나 함수의 반환값으로 사용할 수 있습니다.
typing
모듈의 Callable
은 이러한 함수에 대한 타입 어노테이션을 추가할 때 사용합니다.
예를 들어, 아래 repeat
함수는 첫 번째 매개 변수 greet
를 통해 함수를 인자로 받고 있는데요.
매개 변수에 타입 어노테이션 Callable[[str], str]
를 추가해줌으로써, str
타입의 인자를 하나 받고, 결과값을 str
로 반환하는 함수를 나타내고 있습니다.
from typing import Callable
def repeat(greet: Callable[[str], str], name: str, times: int = 1) -> None:
for _ in range(times):
print(greet(name))
repeat
함수를 호출할 때 넘길 람다 함수를 작성할 때도 동일한 타입 어노테이션을 사용할 수 있습니다.
>>> repeat(lambda name: f"Hi, {name}!", "Python", 2)
Hi, Python!
Hi, Python!
Iterable, Sequence, Mapping, MutableMapping
어떤 함수의 매개 변수에 타입을 표시해 줄 때는 추상적으로 명시해주는 것이 유리한 경우가 많습니다.
예를 들어, 아래 toStrings()
함수는 nums
매개 변수의 타입을 List[int]
대신에 Iterable[int]
로 명시해주고 있습니다.
from typing import Iterable, List
def toStrings(nums: Iterable[int]) -> List[str]:
return [str(x) for x in nums]
따라서 이 함수는 리스트 뿐만 아니라 튜플, 세트까지 처리할 수 있는 유연한 API를 가지게 되었습니다.
>>> toStrings([1, 2, 3])
['1', '2', '3']
>>> toStrings((1, 2, 3))
['1', '2', '3']
>>> toStrings({1, 2, 3})
['1', '2', '3']
typing
모듈은 Iterable
뿐만 아니라 Sequence
, Mapping
, MutableMapping
와 같은 다른 추상 타입을 지원하고 있으니 한 번 활용해보시면 좋을 것 같습니다.
전체 코드
본 포스팅에서 제가 작성한 전체 코드는 아래에서 직접 확인하고 실행해보실 수 있습니다.
마치면서
지금까지 파이썬 코드에 타입 어노테이션을 추가할 때 typing
내장 모듈을 어떻게 활용할 수 있는지 살펴보았습니다.
typing
모듈을 사용할 때 한 가지 주의할 점은 타입 어노테이션(type annotation)을 추가한다고 해서 프로그래밍 언어 차원에서 어떤 제약이 발생하는 것은 아니라는 것입니다.
따라서, 타입 어노테이션을 추가한 코드를 상대로 타입을 검증하기 위해서는 Mypy와 같은 정적 타입 검사기를 사용하는 것을 고려하셔야 겠습니다.
이 부분에 대해서는 별도 포스팅에서 자세히 다루었으니 참고 바랍니다.
마지막으로, typing
모듈에 대한 좀 더 자세한 내용은 파이썬 공식 레퍼런스를 참고 바랍니다.