머신러닝&딥러닝

객체 지향 프로그래밍 #3 Types

seungbeomdo 2023. 1. 17. 12:47
 

객체 지향 프로그래밍 #2 OOP의 특징

객체 지향 프로그래밍 #1 클래스와 인스턴스 파이썬을 제대로 다룰 줄 아는 건지에 대한 의심이 들었다. 전처리, 기술 분석, 회귀 분석, 가설 검정, 시각화 이런 데이터 분석의 프로세스를 구현하

seungbeomdo.tistory.com


1. Type Check

  • 파이썬의 변수들은 모두 타입(Type)을 보유하고 있다. 각 타입마다 연산의 범위와 결과가 달라지기 때문에 견고한 코딩을 위해서는 타입을 잘 지정해줘야 한다.
  • 덧셈을 하는 함수를 정의한다고 하면, 
def cal_add(x, y): #type hint: 어떤 타입의 인자와 결과가 나오는지 기록
  return x + y

 

  • 이때 인자와 결과의 타입을 암묵적으로 정수(int)나 실수(float 타입)라고 가정하지만 그러면 다음과 같은 문제가 발생한다.

  • 숫자형(int or float) 1과 3을 인자로 받을 때는 원하는 결과인 4가 나오지만, 문자형(str) '1'과 '3'을 받을 때는 원하지 않은 결과인 13이 나온다. str 간에 더하기를 하면 자동으로 이어붙이기가 되기 때문에 그렇다.

 

  • 이런 연산을 방지하고 오류 메세지를 출력하기 위해 Type Hint라는 것을 쓴다. 
def cal_add(x: int, y: int) -> int: #type hint: 어떤 타입의 인자와 결과가 나오는지 기록
  return x + y
  • 사실 Type Hint를 표시해놓더라도 해당하는 타입의 인자만 받도록 강제되는 것은 아니다. 조금은 더 코드를 짜야하는데, 우선 isinstance 함수가 유용하게 쓰인다.
  • insinstance 함수는 주어진 변수가 주어진 클래스의 인스턴스인지 조사하는 함수이다.

  • isinstance를 활용해 타입을 검사하는 함수 type_check를 만들어 계산기 함수에 포함시키자.
def type_check(obj, typer) -> None:
  if isinstance(obj, typer):
    pass
  else:
    raise TypeError(f"Type Error: {typer}")

def cal_add(x: int, y: int) -> int: #type hint: 어떤 타입의 인자와 결과가 나오는지 기록
  type_check(x, int)
  type_check(y, int)
  return x + y
  • 원하는 결과를 얻는다.

 

  • 이상은 메서드 객체에서 타입을 지정하는 방법이었고 그 외 객체들은 아래와 같다.
  • Simple 객체
int_var: int = 88
str_var: str = "hello world"
float_var: float = 88.9
bool_var: bool = True​
  • 리스트, 튜플, 딕셔너리 객체
from typing import List, Tuple, Dict
 
list_var: List[str] = ["1", "2", "3"]
tuple_var: Tuple[int, ...] = (1, 3, 4)
dic_var: Dict[str, int] = {"hello": 47}

2. 다양한 상황에서의 Types

  • Final: 어떤 객체가 수정이 불가능하도록 만들고 싶을 때는 Final type을 사용한다.
from typing_extensions import Final

fianl_var = Final[int] = 10
  • Union: 복수의 타입이 허용되도록 하고 싶은 상황에서는 Union type을 사용한다.
from typing import Union

def cal_add(x: Union[int, float], y: Union[int, float]) -> Union[int, float]:
    return x + y
  • Optional: 인자가 None일 수도 있는 경우, 즉 인자가 없을 수도 있는 상황에서는 Optional type을 사용한다.
def cal_add(x: Union[int, float], y: Optional[Union[int, float]] = None) -> Union[int, float]:
    if y:
        return x + y
    else:
        return x
  • Callable: 함수를 인자로 받는 함수일 때는 인자의 타입을 Callable로 사용한다.
def add(a: int, b: int) -> int:
  type_check(a, int)
  type_check(b, int)
  return a + b

from typing import Callable

def how_many(func: Callable[[int, int], int]) -> None:
  print(f'사과 {func(2, 3)}개 남았음')
  • Type Alias: 매우 특수한 타입의 변수가 필요할 때 유저가 임의로 타입을 만들어 사용
from typing_extensions import TypedDict

Value = Union[int, bool, Union[List[str], List[int]], Optional[Dict[str, float]]]

x : Value = 17
  • Generic: 일반화된 타입
  • Generic type은 Union type이나, 혹은 타입을 지정해주지 않는 경우(any)와 어떻게 다를까? Generic type은 인풋으로 받은 인자의 type에 따라서 결과의 type도 달라지는 관계를 표현할 수 있다.
from typing import TypeVar

T = TypeVar('T'. bound = Union[int, float])

def cal_square(x: T) -> T:
	return x ** 2