파이썬에서 모든 것은 객체입니다
파이썬에서는 클래스를 포함한 모든 요소가 객체로 취급됩니다. 그리고 모든 클래스는 type이라는 이름의 클래스의 인스턴스입니다. 흥미로운 점은 type 객체 자체도 다시 type 클래스의 인스턴스라는 사실인데, 이러한 구조야말로 파이썬 객체 모델의 근간을 이루는 핵심 개념입니다.
클래스 객체의 __bases__ 속성을 조사하면 해당 클래스의 상속 계층 구조를 확인할 수 있습니다. 또한 type() 메서드는 매개변수로 전달된 객체의 클래스 타입을 반환하며, 호출 방식에 따라 두 가지 역할을 수행합니다.
- 인자 1개 — type(obj): 전달된 객체의 타입(클래스)을 반환합니다.
- 인자 3개 — type(name, bases, dict): 새로운 type 객체, 즉 새로운 클래스를 동적으로 생성하여 반환합니다.
type()으로 데이터 타입 확인하기
가장 자주 사용되는 데이터 타입들이 어떤 클래스에 속하는지 살펴보겠습니다. 아래 코드에서는 여러 변수를 초기화한 뒤 type()을 호출해 각각의 클래스를 확인합니다.
예제
# Some variables
a = 5
b = 5.2
c = 'hello'
A = [1,4,7]
B = {'k1':'Sun','K2':"Mon",'K3':'Tue'}
C = ('Sky','Blue','Vast')
print(type(a))
print(type(b))
print(type(c))
print(type(A))
print(type(B))
print(type(C))
출력 결과
위 코드를 실행하면 다음과 같은 결과를 얻습니다.
<class 'int'> <class 'float'> <class 'str'> <class 'list'> <class 'dict'> <class 'tuple'>
정수는 int, 실수는 float, 문자열은 str, 리스트는 list, 딕셔너리는 dict, 튜플은 tuple 클래스에 속한다는 것을 한눈에 확인할 수 있습니다.
클래스의 타입은 무엇일까?
그렇다면 앞서 확인한 int, dict, list 같은 클래스들 자체의 타입은 무엇일까요? 한 단계 더 들어가 보면 이들 모두 'type'이라는 클래스에 속한다는 사실을 알 수 있습니다.
예제
print(type(int)) print(type(dict)) print(type(list)) print(type(type))
출력 결과
위 코드를 실행하면 다음과 같은 결과를 얻습니다.
<class 'type'> <class 'type'> <class 'type'> <class 'type'>
심지어 type 자신의 타입조차 type입니다. 즉, type은 자기 자신의 인스턴스이기도 한 파이썬에서 유일무이한 존재입니다.
새로운 객체 타입 동적으로 생성하기
type()에 세 개의 인자를 전달하면 class 문 없이도 새로운 클래스를 동적으로 만들 수 있습니다. 각 인자의 의미는 다음과 같습니다.
- name: 생성할 클래스의 이름
- bases: 상속받을 부모 클래스들을 담은 튜플
- dict: 클래스에 포함시킬 속성과 메서드를 정의한 딕셔너리
예제
Object1 = type('A', (object,), dict(a='Hello', b=5))
print(type(Object1))
print(vars(Object1))
class NewCalss:
a = 'Good day!'
b = 7
Object2 = type('B', (NewCalss,), dict(a='Hello', b=5))
print(type(Object2))
print(vars(Object2))
출력 결과
위 코드를 실행하면 다음과 같은 결과를 얻습니다.
<class 'type'>
{'a': 'Hello', 'b': 5, '__module__': '__main__', '__dict__': <attribute '__dict__' of 'A' objects>, '__weakref__': <attribute '__weakref__' of 'A' objects>, '__doc__': None}
<class 'type'>
{'a': 'Hello', 'b': 5, '__module__': '__main__', '__doc__': None}
첫 번째 예제에서는 object를 부모로 하는 새로운 클래스 A를 만들었고, 두 번째 예제에서는 직접 정의한 NewClass를 부모로 삼아 클래스 B를 생성했습니다. vars() 함수를 사용하면 생성된 클래스의 네임스페이스, 즉 내부에 정의된 속성들을 확인할 수 있으며, 두 경우 모두 결과 타입이 type으로 출력되는 것을 볼 수 있습니다. 이처럼 type()은 런타임에 클래스를 동적으로 정의할 수 있는 강력한 도구이며, 메타클래스와 메타프로그래밍을 이해하는 데 꼭 필요한 기반 지식입니다.