파이썬 타입 어노테이션 : 데이터 타입의 힌트 표기

파이썬 타입 어노테이션“은 변수, 함수 매개변수, 함수 반환 값 등에 대한 타입 정보를 코드에 명시적으로 추가하는 기능입니다. 이는 코드의 가독성을 높이고, 협업 시 코드의 이해와 유지보수를 용이하게 만들어줍니다.

타입 어노테이션은 주로 변수 뒤에 콜론(:)을 사용하여 타입을 명시합니다.

함수의 매개변수에 대해서도 마찬가지 방식으로 사용됩니다.

반환값만 -> 를 사용하여 명시합니다.

기본 사용법은 아래와 같습니다.

기본 사용법

# 변수에 대한 타입 어노테이션
name: str = "John"
age: int = 25
height: float = 175.5

# 함수 매개변수와 반환 값에 대한 타입 어노테이션
def greet_person(person_name: str, person_age: int) -> str:
    greeting = f"Hello, {person_name}! You are {person_age} years old."
    return greeting

# 함수 호출
result = greet_person(name, age)
print(result)

파이썬 타입 어노테이션 장점

주요 이점설명
가독성 향상명시적인 타입 정보를 통해 코드를 이해하기 쉽게 만듭니다.
타입 검사 도구 활용타입 검사 도구를 사용하여 코드의 타입 일치성을 검사하고 버그를 방지할 수 있습니다.
문서화 향상코드의 동작과 함께 예상되는 타입 정보를 문서화하여 문서의 품질을 높입니다.

파이썬 타입 어노테이션 이용시 주의점

주의점설명
동적 타이핑과 조화파이썬은 동적 타이핑 언어이므로, 타입 어노테이션은 코드 가독성을 높이는데 활용되지만 런타임에는 영향을 미치지 않음.
필수는 아님타입 어노테이션은 필수가 아니며, 코드의 명확성을 해치지 않을 경우 생략 가능.
버전Python 3.5 이상의 버전을 사용하여 타입 어노테이션을 활용.

3.9 버전 이상 부터는 typing 모듈이 필요 없음

기본적인 타입 힌트

List, Tuple, Dict, Set

이들은 각각 리스트, 튜플, 딕셔너리, 세트를 나타내는 타입 힌트입니다.

from typing import List, Dict, Tuple, Callable

def process_data(data: List[int]) -> Dict[str, Tuple[int, Callable]]:
    result = {}
    for value in data:
        result[f"key_{value}"] = (value, lambda x: x * 2)
    return result

위의 주의점에 언급했지만 기본적인 타입 힌트는 3.9이상 버전 부터는 typing 모듈이 필요 없습니다.

위와 동일한 type annotation을 typing 모듈 없이 아래와 같이 구현 할 수 있습니다.

def process_data(data: list[int]) -> dict[str, tuple[int, callable]]:
    result = {}
    for value in data:
        result[f"key_{value}"] = (value, lambda x: x * 2)
    return result

numpyDataFrame에서도 아래와 같이 type annotation을 사용할 수 있습니다.

from typing import List, Tuple
import numpy as np

# 1D 배열
array_1d: np.ndarray[float] = np.array([1.0, 2.0, 3.0])

# 2D 배열
array_2d: np.ndarray[List[float]] = np.array([[1.0, 2.0], [3.0, 4.0]])

# 다차원 배열
array_3d: np.ndarray[List[List[float]]] = np.array([[[1.0, 2.0], [3.0, 4.0]], [[5.0, 6.0], [7.0, 8.0]]])

# 데이터프레임
data_frame: pd.DataFrame[int, str] = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]}, index=['X', 'Y', 'Z'])

# 시리즈
series: pd.Series[str] = pd.Series(['apple', 'banana', 'cherry'], index=['A', 'B', 'C'])

# 딕셔너리를 활용한 데이터프레임
data_frame_dict: pd.DataFrame[Dict[str, int]] = pd.DataFrame({'A': {'X': 1, 'Y': 2, 'Z': 3}, 'B': {'X': 4, 'Y': 5, 'Z': 6}})

Optional

어떤 타입 또는 None을 나타내는 타입 힌트로, 예외 상황에 유용합니다.

from typing import Optional

def find_item(name: str) -> Optional[str]:
    # 아이템을 찾으면 해당 아이템, 찾지 못하면 None 반환
    pass

Union

여러 타입 중 하나일 수 있는 타입을 표현합니다.

from typing import Union

def process_input(data: Union[str, List[int]]) -> None:
    # 함수 내용
    pass

Generic

클래스나 함수에서 제네릭을 사용하여 임의의 타입을 나타낼 수 있습니다.

from typing import TypeVar, Generic

T = TypeVar('T')

class Box(Generic[T]):
    def __init__(self, content: T):
        self.content = content

string_box = Box("Hello, World!")
int_box = Box(42)

위의 코드에서 T는 임의의 타입을 의미하며, Box 클래스를 사용할 때에는 어떤 타입이든 넣을 수 있습니다.

callable

Callable은 함수의 타입을 표현할 때 사용됩니다. 매개변수와 반환 값의 타입을 정의하여 함수의 모양을 명시할 수 있습니다.

from typing import Callable

def apply_operation(operation: Callable[[int, int], int], a: int, b: int) -> int:
    return operation(a, b)

# 덧셈 함수를 만들어 적용해보자
def add(x: int, y: int) -> int:
    return x + y

result = apply_operation(add, 3, 4)  # 3 + 4 = 7
  • Callable: 이 타입은 함수를 나타냅니다.
  • [int, int]: 함수의 매개변수로 두 개의 int 타입을 받는다는 것을 의미합니다.
  • int: 함수의 반환 값이 int 타입이라는 것을 나타냅니다.

그래서 Callable[[int, int], int]은 “두 개의 정수를 받아 하나의 정수를 반환하는 함수”를 의미합니다.

  • a: int, b: int:
    • 이 부분은 함수를 호출할 때 사용되는 인자의 타입을 지정합니다.
    • 여기서 ab는 각각 int 타입이어야 한다는 것을 나타냅니다.

이 두 가지 정보를 동시에 사용하는 것은 반드시 필요하지는 않습니다.

마치며

typing 모듈은 파이썬 코드를 더 강력하고 안정적으로 만드는 데에 큰 도움이 될 것 같습니다.

특히 OptionalUnion 기능은 필요한 순간에 유용하게 쓰일 것 같습니다.

typing 모듈을 몰랐을 때는 함수가 길어질 때만 매개변수와 리턴에만 간단히 몇 번 사용했는데, 복잡한 자료형의 데이터 타입을 명시하는데도 사용할 것 같습니다.

참고하면 좋은 글

Leave a Comment

목차