Python 타이핑: 코드 가독성 향상

PythonBeginner
지금 연습하기

소개

이 튜토리얼에서는 Python 의 typing 모듈을 사용하여 코드에 타입 힌트를 추가하는 방법을 배우게 됩니다. 타입 힌트는 함수가 예상하는 입력 및 출력 타입을 명시적으로 표시하여 코드를 더 읽기 쉽고 유지 관리 가능하게 만드는 데 도움이 됩니다.

기본 타입

타입 힌트는 Python 3.5 에 도입된 기능이며, typing 모듈은 표준 타입 어노테이션을 제공하기 위해 Python 3.5.2 에 추가되었습니다. 타입 힌트 사용을 시작하려면 typing 모듈에서 관련 타입을 가져오세요.

from typing import List, Tuple, Dict

기본 타입에 대한 타입 힌트는 간단합니다. 타입 자체를 힌트로 사용하면 됩니다.

터미널에서 다음 명령을 입력하여 Python 셸을 엽니다.

python3
  1. int 타입의 변수를 정의하고 값을 할당한 다음 출력합니다.
age: int = 25
print(age) #Output: 25
  1. float 타입의 변수를 정의하고 값을 할당한 다음 출력합니다.
temperature: float = 98.6
print(temperature) ## Output: 98.6
  1. bool 타입의 변수를 정의하고 값을 할당한 다음 출력합니다.
is_raining: bool = True
print(is_raining) ## Output: True
  1. str 타입의 변수를 정의하고 값을 할당한 다음 출력합니다.
def greet(name: str) -> str:
    return f"Hello, {name}!"

print(greet("Alice")) ## Output: Hello, Alice!
  1. int 타입의 인자 두 개를 받아 곱하고 결과를 int로 반환하는 함수를 정의합니다.
def multiply(x: int, y: int) -> int:
    return x * y

result = multiply(5, 10)
print(result) ## Output: 50

컨테이너 및 제네릭

컨테이너 타입 (리스트, 딕셔너리, 세트 등) 에 대한 타입 힌트는 제네릭을 사용하여 더 구체적으로 지정할 수 있습니다.

팁: 일련 번호 1-3 의 실험은 Python 셸에서 구현할 수 있으며, 일련 번호 4 의 실험은 WebIDE 에서 구현됩니다.

  1. List[int] 타입의 변수를 정의하고 일부 값을 할당한 다음 출력합니다.
from typing import List
numbers: List[int] = [1, 2, 3, 4, 5]
print(numbers) ## Output: [1, 2, 3, 4, 5]
  1. Dict[str, int] 타입의 변수를 정의하고 일부 키 - 값 쌍을 할당한 다음 출력합니다.
from typing import Dict
ages: Dict[str, int] = {"Alice": 25, "Bob": 30, "Charlie": 35}
print(ages) ## Output: {'Alice': 25, 'Bob': 30, 'Charlie': 35}
  1. Tuple[str, int, float] 타입의 변수를 정의하고 일부 값을 할당한 다음 출력합니다.
from typing import Tuple
person: Tuple[str, int, float] = ("Alice", 25, 5.7)
print(person) ## Output: ('Alice', 25, 5.7)
  1. 정수 리스트를 인수로 받아 새로운 정수 세트로 결과를 반환하는 함수를 정의합니다.

WebIDE 에서 list_to_set.py라는 프로젝트를 생성하고 다음 내용을 입력합니다.

from typing import List, Set

def get_unique_elements(elements: List[int]) -> Set[int]:
    return set(elements)

numbers = [1, 2, 2, 3, 4, 4, 4, 5]
unique_numbers = get_unique_elements(numbers)
print(unique_numbers)  ## Output: {1, 2, 3, 4, 5}

다음 명령을 사용하여 스크립트를 실행합니다.

python list_to_set.py

사용자 정의 타입

사용자 정의 타입과 클래스도 타입 힌트로 사용할 수 있습니다.

팁: 이 실험은 WebIDE 에서 구현됩니다.

  1. name (str)age (int) 타입의 속성과 사람의 이름과 나이를 요약하는 문자열을 반환하는 get_summary 메서드를 가진 Person 클래스를 정의합니다.

WebIDE 에서 str_and_int_to_str.py라는 프로젝트를 생성하고 다음 내용을 입력합니다.

class Person:
    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age
    def get_summary(self) -> str:
        return f"{self.name} is {self.age} years old."

person1 = Person("Alice", 25)
print(person1.get_summary()) ## Output: Alice is 25 years old.

다음 명령을 사용하여 스크립트를 실행합니다.

python str_and_int_to_str.py
  1. xy 속성 (둘 다 float 타입) 과 다른 점을 인수로 받아 두 점 사이의 거리를 반환하는 distance 메서드를 가진 Point 클래스를 정의합니다.

WebIDE 에서 other_to_float.py라는 프로젝트를 생성하고 다음 내용을 입력합니다.

import math

class Point:
    def __init__(self, x: float, y: float):
        self.x = x
        self.y = y
    def distance(self, other: "Point") -> float:
        return math.sqrt((self.x - other.x)**2 + (self.y - other.y)**2)

point1 = Point(0, 0)
point2 = Point(3, 4)
print(point1.distance(point2)) ## Output: 5.0

다음 명령을 사용하여 스크립트를 실행합니다.

python other_to_float.py

타입 별칭

타입 별칭은 특히 복잡한 타입에 대해 더 읽기 쉬운 타입 힌트를 생성할 수 있습니다.

WebIDE 에서 type_aliases.py라는 프로젝트를 생성하고 다음 내용을 입력합니다.

from typing import List, Tuple

Coordinate = Tuple[float, float]
Path = List[Coordinate]

def get_distance(coord1: Coordinate, coord2: Coordinate) -> float:
    return ((coord1[0] - coord2[0])**2 + (coord1[1] - coord2[1])**2)**0.5

start = (0, 0)
end = (3, 4)
print(get_distance(start, end))  ## Output: 5.0

다음 명령을 사용하여 스크립트를 실행합니다.

python type_aliases.py

Optional 과 None

Optional 타입은 값이 특정 타입이거나 None일 수 있을 때 사용될 수 있습니다.

  1. 선택적 int 인수를 받아, None이 아닌 경우 2 를 곱하고, 입력이 None인 경우 결과를 int 또는 None으로 반환하는 함수를 정의합니다.

WebIDE 에서 option_and_none_1.py라는 프로젝트를 생성하고 다음 내용을 입력합니다.

from typing import Optional

def double_or_none(number: Optional[int]) -> Optional[int]:
    if number is not None:
        return number * 2
    else:
        return None

result1 = double_or_none(5)
result2 = double_or_none(None)
print(result1, result2) ## Output: 10 None

다음 명령을 사용하여 스크립트를 실행합니다.

python option_and_none_1.py
  1. 유효한 주소 문자열 또는 None 인 typed attribute address 를 가진 Person 클래스를 정의합니다.

WebIDE 에서 option_and_none_2.py라는 프로젝트를 생성하고 다음 내용을 입력합니다.

from typing import Optional

class Person:
    def __init__(self, name: str, age: int, address: Optional[str]):
        self.name = name
        self.age = age
        self.address = address

person1 = Person("Alice", 25, "123 Main St")
person2 = Person("Bob", 30, None)
print(person1.name, person1.age, person1.address) ## Output: Alice 25 123 Main St
print(person2.name, person2.age, person2.address) ## Output: Bob 30 None

다음 명령을 사용하여 스크립트를 실행합니다.

python option_and_none_2.py

Callable (호출 가능)

Callable 타입은 함수 또는 메서드의 타입을 지정하는 데 사용됩니다.

WebIDE 에서 callable.py라는 프로젝트를 생성하고 다음 내용을 입력합니다.

from typing import Callable

def apply_function(value: int, func: Callable[[int], int]) -> int:
    return func(value)

def double(x: int) -> int:
    return x * 2

print(apply_function(5, double))  ## Output: 10

다음 명령을 사용하여 스크립트를 실행합니다.

python callable.py

Typeddict (타입딕트)

TypedDict는 특정 키와 값 타입을 가진 사용자 정의 딕셔너리를 생성할 수 있도록 합니다.

팁: TypedDict 는 Python 3.8 에 도입되었으므로, 사용하려면 Python 3.8 이상을 실행해야 합니다.

다음은 예시입니다.

WebIDE 에서 typeddict.py라는 프로젝트를 생성하고 다음 내용을 입력합니다.

from typing import TypedDict

class PersonInfo(TypedDict):
    name: str
    age: int

def greet(person: PersonInfo) -> str:
    return f"Hello, {person['name']}! You are {person['age']} years old."

alice_info: PersonInfo = {"name": "Alice", "age": 30}
print(greet(alice_info))  ## Output: Hello, Alice! You are 30 years old.

다음 명령을 사용하여 스크립트를 실행합니다.

python typeddict.py

Newtype (뉴타입)

NewType 은 Python 의 typing 모듈에서 제공하는 타입 힌트로, 기존 타입을 감싸는 새로운 타입을 생성할 수 있게 해줍니다. 이는 변수와 함수 인자에 더 의미론적인 의미를 부여하는 데 유용할 수 있습니다.

다음은 예시입니다.

WebIDE 에서 newtype.py라는 프로젝트를 생성하고 다음 내용을 입력합니다.

그런 다음 다음 Python 스크립트를 실행합니다.

from typing import NewType

UserId = NewType("UserId", int)
OrderId = NewType("OrderId", int)

def get_order(order_id: OrderId) -> str:
    return f"Order with ID: {order_id}"

order_id = OrderId(123)
user_id = UserId(123)

print(get_order(order_id))  ## Output: Order with ID: 123

다음 명령을 사용하여 스크립트를 실행합니다.

python newtype.py

정적 타입 검사 (Static Type Checking) - Python Mypy 사용법

Python 에서 정적 타입 검사는 타입 힌트와 mypy와 같은 정적 타입 검사기를 사용하여 수행할 수 있습니다. 타입 힌트는 변수, 함수 인자 및 반환 값의 예상 타입을 나타냅니다. 다음은 예시입니다.

먼저, mypy를 설치합니다.

pip install mypy

다음은 예시입니다.

WebIDE 에서 mypy.py라는 프로젝트를 생성하고 다음 내용을 입력합니다.

def add_numbers(x: int, y: int) -> int:
    return x + y

result = add_numbers(2, 3)
print(result)

그런 다음 스크립트에서 mypy를 실행합니다.

mypy mypy.py

이렇게 하면 코드에서 발견된 모든 타입 불일치에 대한 피드백을 얻을 수 있습니다.

요약

이것이 전부입니다! 이제 Python typing 모듈을 사용하여 코드에 타입 힌트를 추가하는 방법을 알게 되었습니다. 타입 힌트는 코드 가독성과 유지 관리성을 크게 향상시켜 대규모 코드베이스로 작업하고 다른 사람들과 협업하는 것을 더 쉽게 만들어줍니다.