Python 메타클래스(Metaclass)는 클래스를 생성하는 클래스다. 일반 클래스가 인스턴스를 만들 듯이, 메타클래스는 클래스 자체를 만든다. Python의 기본 메타클래스는 type이다.
메타클래스 기본 개념
python
# type()으로 클래스 동적 생성
MyClass = type('MyClass', (object,), {'x': 42, 'hello': lambda self: 'Hi'})
obj = MyClass()
print(obj.x) # 42
print(obj.hello()) # Hi
# 메타클래스 확인
print(type(int)) # <class 'type'>
print(type(MyClass)) # <class 'type'>
커스텀 메타클래스
python
class SingletonMeta(type):
_instances = {}
def __call__(cls, *args, **kwargs):
if cls not in cls._instances:
cls._instances[cls] = super().__call__(*args, **kwargs)
return cls._instances[cls]
class Database(metaclass=SingletonMeta):
def __init__(self):
self.connection = "connected"
db1 = Database()
db2 = Database()
print(db1 is db2) # True — 같은 인스턴스
__new__와 init 훅
python
class ValidateMeta(type):
def __new__(mcs, name, bases, namespace):
# 클래스 정의 시점에 실행
for key, val in namespace.items():
if not key.startswith('_') and callable(val):
if not hasattr(val, '__doc__') or val.__doc__ is None:
raise TypeError(f'{name}.{key}에 docstring이 없습니다')
return super().__new__(mcs, name, bases, namespace)
class MyService(metaclass=ValidateMeta):
def process(self):
"""데이터를 처리한다."""
pass
init_subclass (Python 3.6+)
메타클래스 없이 서브클래스 생성을 제어하는 더 간단한 방법:
python
class Plugin:
_registry = {}
def __init_subclass__(cls, plugin_name=None, **kwargs):
super().__init_subclass__(**kwargs)
if plugin_name:
Plugin._registry[plugin_name] = cls
class AudioPlugin(Plugin, plugin_name='audio'):
pass
class VideoPlugin(Plugin, plugin_name='video'):
pass
print(Plugin._registry)
# {'audio': <class 'AudioPlugin'>, 'video': <class 'VideoPlugin'>}
활용 사례
| 용도 | 예시 |
|---|
| ORM | Django Model 클래스 필드 수집 |
| 싱글턴 | 인스턴스 유일성 보장 |
| 인터페이스 검증 | 추상 메서드 구현 강제 |
| 자동 등록 | 플러그인 시스템 |
| 로깅/프로파일링 | 메서드 자동 래핑 |
관련 개념