1. 데이터 타입의 일반화
파이썬 코드를 보다 보면 T = TypeVar(‘T’)과 Generic이라는 표현을 종종 보게 됩니다. T = TypeVar(‘T’)를 먼저 살펴보면 T는 형 변수(type variable)이고 ‘T’는 형 변수의 이름(variable name)입니다. TypeVar로 정의된 T는 어느 자료형이든 될 수 있는 변수가 됩니다. 기본 자료형인 int, string 부터 사용자가 만든 class까지 무엇이든 될 수 있습니다. 그래서 데이터 타입의 일반화입니다.
2. TypeVar을 알기 위한 type hints
파이썬에서는 typing (support for type hints) 이라는 패키지가 있습니다. 파이썬 개발자가 프로그래밍할 때 전달되는 인자 및 반환 값이 어떤 자료형이었으면 좋겠는지에 대한 주석이라고 볼 수 있습니다. 주석이라고 표현한 이유는 설령 명시한 것과 다른 자료형이 들어가더라도 작동에 문제가 없기 때문입니다. 덧셈 함수에 대한 코드를 예로 들면 다음과 같습니다. a, b의 int, float 등 어떤 값이 입력되더라도 두 값의 덧셈 결과를 반환합니다.
def add(a, b):
return a + b
같은 코드를 type hints를 사용하면 int 자료형만 받을 것이며, 반환되는 결과도 int 자료형으로 하고 싶을 경우 아래와 같이 코드를 짤 수 있습니다. 물론 이를 무시하고 값을 입력해도 결과는 정상적으로 출력됩니다.
def add(a: int, b: int) -> int:
return a + b
TypeVar()을 사용하여 T를 정의하면 type hints로 T를 사용할 수도 있습니다. 이렇게 선언할 경우 a, b로 정수형, 실수형, 문자열 등 덧셈 연산을 할 수 있는 모든 자료형을 받겠다는 것을 의미합니다.
from typing import TypeVar
T = TypeVar('T')
def add(a: T, b: T) -> T:
return a + b
T의 후보군을 정할 수도 있습니다. 형 변수 이름 뒤에 " , "로 구분하고 int, float을 써주면 int, float로 자료형을 제한하게 됩니다. 파이썬 버전에 따라서는 여기서 오류를 발생시키기도 합니다.
from typing import TypeVar
T = TypeVar('T', int, float)
def add(a: T, b: T) -> T:
return a + b
https://stackoverflow.com/questions/48417071/purpose-of-name-in-typevar-newtype
3. 제너릭 프로그래밍
Generic은 제너릭 프로그래밍(generic programming)과 관련이 깊습니다. 제너릭 프로그래밍은 자료형에 상관없이 동작할 수 있는 프로그램을 만들어서 개발된 프로그램의 재사용성을 높이는 프로그래밍 방식입니다. 아래의 예제는 사람의 정보를 저장하는 예제로 이름과 전화번호를 저장합니다.
main.py
from typing import TypeVar, Generic
T = TypeVar('T', str, int)
class PersonInfo(Generic[T]): # 사람의 정보를 저장하는 클래스
def __init__(self, name: str, phone: T):
self.name = name
self.phone = phone
def get_info(self): # 사람의 정보 출력
print(f"name : {self.name}")
print(f"phone : {self.phone}")
print()
if __name__ == "__main__":
student1 = PersonInfo("John", 1234567)
student2 = PersonInfo("Smith", "234-5678")
student3 = PersonInfo("Jack", [1, 1, 1, 2, 2, 2, 2])
student1.get_info()
student2.get_info()
student3.get_info()
PersonInfo 클래스에서는 Generic[T] 클래스를 상속받습니다. 단순하게 얘기하면 Generic[T]를 사용하여서 PersonInfo가 T를 사용할 수 있도록 하겠다는 것입니다. 누군가는 정수형으로 전화번호를 적을 수도 있고 누군가는 “-”를 포함하여 문자형으로 전화번호를 입력할 수도 있습니다. 그렇기 때문에 int와 str 두 종류의 자료형으로 받겠다고 한정한 것입니다. 물론 이를 무시하고 리스트로 입력해도 문제없이 실행됩니다.
name : John
phone : 1234567
name : Smith
phone : 234-5678
name : Jack
phone : [1, 1, 1, 2, 2, 2, 2]
여기까지가 TypeVar과 Generic에 대한 설명입니다. TypeVar은 형 변수를 정의하는 데 사용되고, Generic은 정의된 TypeVar을 클래스 내부에서 사용하기 위해서 사용됩니다. 이들은 정말 하나의 힌트입니다. 코드의 가독성을 높일 수 있는 매우 좋은 힌트입니다.
4. 형 변수의 이름은 왜 필요한가요?
파이썬 버전에 따라서는 제한된 형 변수의 자료형 이외의 자료형이 입력될 경우 형 변수의 이름이 포함된 오류를 발생시킵니다. 그렇기 때문에 무엇이 문제인지 찾기 위해서 반드시 형 변수와 형 변수의 이름은 동일하게 통일해야 합니다.
from typing import TypeVar
T = TypeVar('N', int, float)
if __name__ == "__main__":
print(f"T: {T.__name__}")
T: N
만약 둘을 다르게 할 경우 Visual Studio Code에서는 아래와 같이 경고를 보냅니다.
TypeVar must be assigned to a variable named "N"
5. 감사 글
이 글은 항상 게으르다고 하시지만 너무나도 부지런하신 분의 질문 덕분에 탄생한 글입니다.
https://keizikang.tistory.com/m
긴 글 읽어주셔서 감사합니다.
글과 관련된 의견은 언제든지 환영입니다.
댓글