이 글은 파이썬 문서를 참고해 파이썬에서의 타입 힌트, 또는 어노테이션 문법을 정리한 글입니다. 이 글은 Python 3.10을 기준으로 작성됐습니다.
변수
변수는 변수명 뒤에 :
를 이용해 타입을 명시해줍니다.
x: int = 10
y: str = "abc"
z: bool = True
리스트
x: list = [1, "a", []]
y: list[int] = [1, 2, 3]
z: list[int | str] = [1, 2, "a"]
딕셔너리
x: dict = {}
y: dict[str, int] = {"a": 1, "b": 2, "c": 3}
튜플
x: tuple = (1, "2", 3)
y: tuple[int, str, int] = (1, "2", 3)
유니온 타입
파이썬 3.10부터 Union[int, str]
과 같은 타입을 |
를 사용해 만들 수 있는 기능이 추가되었습니다.
x: int | str = 1 # a: Union[int, str]과 동일합니다
x = "b"
b: int | None = 1 # b: Optional[int]와 동일합니다
b = None
함수
def add(a: int, b: int) -> int:
return a + b
Optional parameter의 경우 타입 어노테이션 이후에 기본값을 정해줍니다.
def foo(a: int = 0) -> int:
return a
Callable
Callable[ArgumentTypes, ReturnType]
을 이용해 함수 타이핑이 가능합니다.
...
를 이용하면 함수의 ReturnType
만을 결정해줄 수 있다.
from collections.abc import Callable
add_function: Callable[[int, int], int] = add
# OR
add_function: Callable[..., int] = add
Generics
Generic Class
제네릭 클래스는 전부 Generic
이라는 추상 클래스를 상속합니다. TypeVar
을 이용해 제네릭 타입을 사용할 수 있습니다.
from typing import Generic, TypeVar
T = TypeVar("T")
class MyList(Generic[T]):
def __init__(self):
self.my_list: list[T]
def append(self, item: T):
self.my_list.append(item)
여러개의 제네릭 타입을 사용할 수도 있습니닫.
KeyType = TypeVar("KeyType")
ValueType = TypeVar("ValueType")
class MyDict(Generic[KeyType, ValueType]):
def __init__(self):
self.my_dict: dict[KeyType, ValueType]
def add(self, key: KeyType, value: ValueType):
self.my_dict[key] = value
Generic Function
제네릭 클래스와 마찬가지로 TypeVar
을 사용해 제네릭 함수를 작성할 수 있습니다.
from typing import Callable, Iterable, TypeVar
T1 = TypeVar("T1")
T2 = TypeVar("T2")
def my_map(func: Callable[[T1], T2], iterables: Iterable[T1]) -> Iterable[T2]:
return map(func, iterables)
ParamSpec
ParamSpec
은 주로 Callable
의 파라미터를 다른 Callable
로 넘겨주고 싶을 때 사용합니다.
예를 들어 아래 기본 함수에 경과 시간을 출력하는 기능을 추가해주는 함수가 있습니다. 이 함수를 사용해 만든 함수는 파라미터의 타이핑이 되지 않는데 ParamSpec
을 쓰면 이 문제를 해결할 수 있습니다.
# 코드 출처: https://www.geeksforgeeks.org/timing-functions-with-decorators-python/
from time import time
def timer_func(func):
# This function shows the execution time of
# the function object passed
def wrap_func(*args, **kwargs):
t1 = time()
result = func(*args, **kwargs)
t2 = time()
print(f'Function {func.__name__!r} executed in {(t2-t1):.4f}s')
return result
return wrap_func
def foo(x: int, y: int) -> int:
return x + y
timed_foo = timer(foo)
timed_foo("a", "b") # No warning
ParamSpec
을 사용해 타이핑한 경우
from time import time
from typing import Callable, ParamSpec, TypeVar
T = TypeVar("T")
P = ParamSpec("P")
def timer(func: Callable[P, T]) -> Callable[P, T]:
def wrap_func(*args: P.args, **kwargs: P.kwargs):
t1 = time()
result = func(*args, **kwargs)
t2 = time()
print(f"Function {func.__name__!r} executed in {(t2-t1):.4f}s")
return result
return wrap_func
def foo(x: int, y: int) -> int:
return x + y
timed_foo = timer(foo)
timed_foo("a", "b") # Warning