본문 바로가기
C.W.K.
Stream
Lesson 01 of 05 · published

타입 힌트 — 실행을 바꾸지 않는 검사 가능한 문서

~22 min · type-hints, annotation, Optional, Union

Level 0호기심
0 XP0/93 lessons0/23 achievements
0/100 XP to next level100 XP to go0% complete

Python의 어노테이션은 __annotations__에 남고 mypy·pyright·IDE가 읽지만 인터프리터가 강제하지 않아. 매개변수에는 : type, 반환에는 -> type을 쓰고 Python 3.9 이상에서는 list[int] 같은 내장 제네릭을 써.

X | None은 값이 없을 수 있음을, X | Y는 여러 허용 타입을 나타내. Any는 검사를 끄는 탈출구이고 object는 타입을 모르는 채 안전하게 제한하므로 둘을 구분해.

Code

매개변수와 반환값 어노테이션·python
def greet(name: str, age: int) -> str:
    return f"hi {name}, age {age}"

# 변수 어노테이션
user_id: int = 42
users: list[str] = ["alice", "bob"]
config: dict[str, int] = {"port": 8000, "workers": 4}

# 어노테이션이 함수에 저장
print(greet.__annotations__)
# {'name': <class 'str'>, 'age': <class 'int'>, 'return': <class 'str'>}

# 런타임에서는 강제하지 않음 — 런타임에 작동, mypy 가 잡음
greet(123, "oops")
내장 컨테이너 제네릭·python
# 옛 스타일 (여전히 작동)
from typing import List, Dict, Tuple, Set
def old_style(items: List[int]) -> Dict[str, int]:
    return {str(i): i for i in items}

# 현대 스타일 (3.9+) — 선호
def modern(items: list[int]) -> dict[str, int]:
    return {str(i): i for i in items}

# Tuple — 고정 크기와 가변 크기
Point = tuple[float, float]                  # 정확히 2 floats
MixedTuple = tuple[int, str, bool]            # 위치별 특정 타입
IntList = tuple[int, ...]                     # 가변 길이, 모두 int
None이 가능한 타입과 | 연산자·python
# 옛 스타일
from typing import Optional, Union
def old(x: Optional[int]) -> Union[str, None]:
    if x is None:
        return None
    return str(x)

# 현대 (3.10+)
def modern(x: int | None) -> str | None:
    if x is None:
        return None
    return str(x)

# 디폴트 값 패턴 — None 의 가장 흔한 사용
def fetch(key: str, default: str | None = None) -> str | None:
    return {"a": "alpha"}.get(key, default)
Any와 object의 차이·python
from typing import Any

def accept_anything(x: Any) -> int:
    # 타입 체커가 x 에 *어떤* 연산도 허용
    return x.completely_made_up_method()      # mypy: OK

def accept_object(x: object) -> int:
    # 타입 체커가 속성 접근 전 narrow 요구
    if isinstance(x, str):
        return len(x)
    raise TypeError

# Any 사용 — 타입 없는 라이브러리, 진짜 동적 데이터, gradual typing.
# object 사용 — '어떤 객체', 나중에 isinstance 로 narrow 할 때.
복잡한 타입에 이름 붙이기·python
# 타입 alias 가 복잡한 타입에 한 번 이름 붙이게
from typing import Callable

UserId = int
UserData = dict[str, str | int | None]
Callback = Callable[[str, int], bool]

def process_user(uid: UserId, data: UserData, on_done: Callback) -> None:
    if on_done("start", uid):
        print("processed", data)

# 3.12+ 명시적 type 문
# type UserId = int    — TypeAlias 로 인식

External links

Exercise

top_n(items: list[dict[str, int]], n: int = 3, key: str = 'score') -> list[dict[str, int]]를 작성하고 점수 내림차순 상위 항목을 돌려줘. 올바른 호출과 int를 넘긴 잘못된 호출을 mypy가 어떻게 구분하는지 확인해.

Progress

Progress is local-only — sign in to sync across devices.
이 페이지에서 버그를 발견하셨거나 피드백이 있으세요?문제 신고

댓글 0

🔔 답글 알림 (로그인 필요)
로그인댓글을 남기려면 로그인해 주세요.

아직 댓글이 없어요. 첫 댓글을 남겨보세요.