- 개요
파이썬에서 메타 클래스는 설계자가 정의한 방식으로 동작하므로 클래스를 유연하게 사용할 수 있다
파이썬에서 메타 클래스를 만드는 방식은 다음과 같이 구분할 수 있다
- type 함수를 사용하여 정의하는 방식
- type 메타 클래스를 상속받아 정의하는 방식
type 함수를 사용하여 메타 클래스를 정의하는 경우 사용방법이 간단하다는 장점이 있지만,
인스턴스의 생성 -> 초기화 -> 호출까지의 과정은 확장할 수 없다는 단점이 있다
반대로 type 클래스를 상속받아 메타 클래스를 정의하는 방법은 많이 복잡하지만,
__new__ , __init__, __call__ 메서드를 오버라이드하여 인스턴스에 대한 과정을 확장할 수 있다
1) type 함수를 사용한 메타 클래스 생성
def custom_multiple(self, d):
for i in range(len(self)):
self[i] = self[i] * d
def custom_replace(self, old, new):
while old in self:
self[self.index(old)] = new
CustomList1 = type(
'CustomList1',
(list,),
{
'desc' : '커스텀 리스트 1',
'custom_multiple' : custom_multiple,
'custom_replace' : custom_replace,
}
)
c1 = CustomList1([1,2,3,4,5,6,7,8,9])
c1.custom_multiple(1000)
print(f"{c1}")
c1.custom_replace(1000, 7777)
print(f"{c1}")
print(f"{c1.desc}")
type 함수를 사용하여 기존의 List 클래스에서 기능을 확장한 메타 클래스를 만들어본다
우선 해당 클래스에서 사용할 2개의 메서드를 생성하였다
각각 리스트의 인덱스의 데이터에 값을 곱하는 함수와 리스트의 인덱스의 데이터를 교체하는 함수이다
type 함수를 사용하여 CusomList 메타 클래스를 생성한다
인자로 해당 클래스의 이름 / 부모 클래스 / 해당 클래스의 프로퍼티와 메서드를 넣어준다
생성한 CustomList 메타 클래스에서 인스턴스 c1을 생성하고 프로퍼티를 설정한다
이후 메서드를 호출하여 결과를 확인한다

출력된 결과는 위와 같다
우선, custom_multiple 메서드를 호출하여 1~9까지의 값에 1000이 곱해진 것을 확인할 수 있다
다음으로 custom_replace 메서드를 호출하고 1000의 값이 7777로 교체된 것을 확인할 수 있다
마지막으로 c1 인스턴스의 desc 프로퍼티에 접근하여 잘 출력된 것도 확인할 수 있다
2) type 클래스를 상속받아 메타 클래스 생성
type 클래스를 상속받아 메타 클래스를 만드는 경우 필요한 메서드를 내부에서 정의해야 한다
필요한 메서드의 경우 다음과 같다
- __new__ : 클래스의 인스턴스를 생성하는 함수
- __init__ : 인스턴스를 초기화하는 함수
- __call__ : 인스턴스를 호출하는 함수
위 3가지의 함수의 호출 순서는 __new__ -> __init__ -> __call__ 순서로 진행된다
또한 __new__와 __call__ 함수의 경우 return을 작성하여 인스턴스를 반환해야 한다
...
class CustomListMeta(type):
def __new__(metacls, name, bases, namespace):
namespace['desc'] = '커스텀 리스트2'
namespace['custom_multiple'] = custom_multiple
namespace['custom_replace'] = custom_replace
return type.__new__(metacls, name, bases, namespace)
def __init__(self, object_or_name, bases, dict):
super().__init__(object_or_name, bases, dict)
def __call__(self, *args, **kwargs):
return super().__call__(*args, **kwargs)
CustomList2 = CustomListMeta('CustomList2',(list, ),{})
c2 = CustomList2([1, 2, 3, 4, 5, 6, 7, 8, 9])
c2.custom_multiple(100)
print(f"{c2}")
c2.custom_replace(100, 777)
print(f"{c2}")
print(f"{c2.desc}")
print(f"{CustomList2.__mro__}")
type 클래스를 상속받은 CustomListMeta 메타 클래스를 생성하였다
또 내부에 __new__, __init__, __call__ 함수를 정의한다
__new__ 메서드에서는 metacls, name, bases, namespace의 4개의 인자를 사용하여
메타 클래스 / 클래스의 이름 / 부모 클래스 / 프로퍼티와 메서드를 정의해야 한다
마지막에 type 클래스의 __new__ 함수에 인자를 넘겨주어 인스턴스를 생성하고 반환한다
__init__ 메서드에서는 object_or_name, bases, dict의 3개의 인자를 사용하여
메타 클래스의 이름 / 부모 클래스 / 프로퍼티와 메서드를 정의한다
위의 구조를 완성하여 메타 클래스의 인스턴스를 완성한 구조로 초기화한다
__call__ 메서드에서는 부모 버전의 __call__ 메서드를 호출하고
인자를 넘겨주어 넘겨준 파라미터로 구성된 인스턴스를 호출하고 반환한다
최종적으로 CustomListMeta 메타 클래스를 사용하여 CustomList2 클래스를 생성하고
해당 클래스의 인스턴스 c2를 통해 메타 클래스의 동작을 확인한다
메서드와 프로퍼티에 접근한 후에, CustomList2의 부모 클래스를 __mro__ 메서드로 확인한다

실행 결과는 위와 같다
인스턴스에 대한 메타 클래스의 메서드 호출이 문제없이 이뤄졌고 프로퍼티인 desc도 출려되었다
또 CustomList2의 부모 클래스인 list 클래스도 확인할 수 있다
'Python > 파이썬 오픈소스 배포' 카테고리의 다른 글
| Descriptor (2) (0) | 2025.07.08 |
|---|---|
| Descriptor (1) (0) | 2025.07.07 |
| 메타 클래스 (2) (0) | 2025.07.05 |
| 메타 클래스 (1) (0) | 2025.07.04 |
| 메서드 오버로딩 (0) | 2025.07.02 |