가. Type Hint
1) 기본 자료형
•
기본 자료형으로 타입 힌트 작성
int_var: int = 11
str_var: str = "hello"
float_var: float = 1.123
Python
복사
2) collections
•
typing 패키지에서 제공 타입 활용
→ 리스트 변수에 대해 list X, List(from typing package)
•
콜렉션 내 구성요소에 대한 타입 작성 권장
from typing import List, Tuple, Dict
list_var: List[str] = ["hello", "world"]
tuple_var: Tuple[int] = (1, 2, 3)
dict_var: Dict[int, str] = {1: "test"}
Python
복사
나. Type Checking Tool
파이썬 런타임에서 type hint를 무시하므로 type checking tool 활용 필요
1) mypy
•
대중적으로 널리 사용되는 type checking tool
•
pip에서 설치 지원
2) pyright
•
MS에서 개발한 type checking tool
•
빠른 속도 강점
•
pip 설치 지원 X
3) 실행
•
기능 개발에 따른 타입 체킹의 방법으로, 개발된 기능을 독립적인 스크립트 파일로 옮긴 후 스크립트 파일에 대해 타입 체킹을 실행하는 방식이 있음.
•
mypy 실행 명령: mypy <script file> && python <script file>
→ Pyright의 경우, mypy 대신 pyright 명령
다. Types
1) Callable Type
•
Callable[[]]: 매개변수로 전달되는 함수에 대한 타입
•
예시
from typing import Callable
def test_callable(func: Callable[[int, int], str]) -> str:
return func(1, 2)
def print_params(a: int, b: int) -> str:
return f'{a}, {b}'
print(test_callable(print_params))
Python
복사
2) Class Type
•
클래스 객체에 대한 타입
•
클래스 정의부분에 클래스 자체에 대한 타입 선언 시 큰따옴표로 감싸야 한다
→ 큰 따옴료로 감싸지 않으면, 클래스 타입이 정의되지 않은 상태이기 때문에 해당 클래스를 타입으로 사용할 수 없다
→ python 3.10 이상부터는 큰 따옴표가 없어도 동작
•
예시
from typing import Optional
class Human:
def __init__(self, a: int, other: Optional["Human"] = None):
self.a = a
self.other = other
def say(self) -> int:
return self.a
def say_from_other(self) -> int:
if self.other is None:
return 0
return self.other.say()
mj = Human(1)
k = Human(2, mj)
print(k.say())
print(k.say_from_other())
Python
복사
3) Union Type
•
하나의 변수에 두 개 이상의 타입을 지정할 수 있도록 정의
•
예시
from typing import Union
class Human:
def __init__(self, a: Union[int, str]):
self.a = a
def say(self) -> Union[int, str]:
return self.a
def listen_to_human(human: Human) -> Union[int, str]:
return human.say()
mj = Human(1)
jj = Human("hello")
print(listen_to_human(mj))
print(listen_to_human(jj))
Python
복사
4) Optional Type
•
Union Type의 일종으로 None Type을 기본 기본값으로 포함하고 있음
→ Union[str, None] == Optional[str]
→ None Type에 대한 Union Typing을 실무에서 많이 쓰기 때문에 간결한 typing을 위해 제공
•
예시
from typing import Optional
def add_small_int(a: int, b: int) -> Optional[int]:
if a > 16 or b > 16:
return None
return a + b
print(add_small_int(5, 6))
print(add_small_int(19, 6))
Python
복사
5) Final Type
•
속성값을 상수로 지정하여 추후 값 수정을 막는다
→ 파이썬 인터프리터는 공식적으로 상수를 지원하지 않음. 일반적으로 대문자로 쓰는 방식은 파이썬 커뮤니티 안에서의 합의일 뿐임
•
예시
from typing_extensions import Final
FIRST_STATE: Final = "HTTTD"
FIRST_STATE = "HHHHH" # error: Cannot assign to final name "FIRST_STATE"
Python
복사
6) Type Alias
•
타입 별칭을 사용하는 이유: 타입이 복잡하게 정의될 경우, 타입 별칭 사용에 따라 복잡한 타입을 재사용할 수 있음
→ 복잡한 타입에 별칭을 정의함으로서 전체적인 코드가 명확해진다
•
예시
from typing import Union, Optional, Dict
ComplexType = Union[int, str, Optional[Dict[str, float]]]
def print_complex_data(a: ComplexType):
print(a)
print_complex_data("hello")
print_complex_data(123)
Python
복사
7) TypedDict
•
TypedDict 활용할 수 있는 경우: JSON으로 데이터를 주고 받을 때, 키값이 고정된 JSON 객체에 맵핑되는 Dictionary를 정의할 수 있음
•
TypedDict를 상속 받은 class로 정의
•
예시
from typing_extensions import TypedDict
class SuccessResponse(TypedDict):
status: str
code: int
response: SuccessResponse = {"status": "success", "code": 200}
print(response)
Python
복사
8) Generic Type
•
사용자가 지정한 하나의 타입에 여러 종류의 타입을 동적으로 지정할 수 있음
•
Generic Type의 경우, 타입 체킹 툴에 따라 다르게 타입을 확인하는 경우가 있으므로 문서를 참고할 필요가 있음
•
Generic Type의 변수명은 명시성을 위해 대문자 하나로 통칭하는 경우가 많음
•
예시) Generic with function
from typing import TypeVar, Generic
# pyright version
# T = TypeVar("T", int, float, str)
# H = TypeVar("H", int, float, str)
T = TypeVar("T")
H = TypeVar("H")
def test_generic(x: T) -> T:
return x
print(f'test_generic: {test_generic(12)}')
Python
복사
•
예시) Generic with class
from typing import TypeVar, Generic
T = TypeVar("T")
H = TypeVar("H")
class Human(Generic[T, H]):
def __init__(self, a: T, b: H):
self.a = a
self.b = b
def say_a(self) -> T:
return self.a
class Engineer(Generic[T, H], Human[T, H]):
def say_b(self) -> H:
return self.b
mm = Human[int, str](1, "hy")
jj = Human[str, int]("hello", 123)
mj = Engineer[int, float](9, 3.14)
print(f'mm: {mm.say_a()}')
print(f'jj: {jj.say_a()}')
print(f'mj: {mj.say_b()}')
Python
복사