파이썬 메타프로그래밍 마스터: 고급 메타클래스 기법
파이썬에서 메타프로그래밍(Metaprogramming)은 자기 자신을 인식하고 조작할 수 있는 코드를 작성하는 관행을 말합니다. 메타클래스(Metaclasses)는 파이썬 메타프로그래밍의 강력한 도구로, 클래스가 생성되고 행동하는 방식을 커스터마이즈할 수 있게 합니다. 메타클래스를 사용하면 동적 코드 생성과 리플렉션을 통해 더 유연하고 효율적인 프로그램을 만들 수 있습니다.
파이썬 메타프로그래밍에는 데코레이터와 메타클래스 같은 기법이 포함됩니다. 이 튜토리얼에서는 동적 코드 생성과 리플렉션을 탐구하며 메타클래스를 활용한 메타프로그래밍을 학습합니다.
메타클래스 정의하기
파이썬 메타프로그래밍에서 메타클래스는 프로그램에 고급 기능을 부여합니다. 그중 `__prepare__()` 메서드는 클래스 본문이 실행될 네임스페이스를 커스터마이즈할 수 있게 합니다.
이 메서드는 클래스 본문 코드 실행 전에 호출되어, 클래스 네임스페이스를 추가 속성이나 메서드로 초기화하는 방법을 제공합니다. `__prepare__()` 메서드는 클래스메서드로 구현해야 합니다.
예제: `__prepare__()` 메서드 활용
class MyMetaClass(type):
@classmethod
def __prepare__(cls, name, bases, **kwargs):
print(f'{name} 네임스페이스 준비 중')
# 네임스페이스 준비 커스터마이즈
custom_namespace = super().__prepare__(name, bases, **kwargs)
custom_namespace['CONSTANT_VALUE'] = 100
return custom_namespace
# 커스텀 메타클래스 사용 클래스 정의
class MyClass(metaclass=MyMetaClass):
def __init__(self, value):
self.value = value
def display(self):
print(f"Value: {self.value}, Constant: {self.__class__.CONSTANT_VALUE}")
# 인스턴스 생성 및 테스트
obj = MyClass(42)
obj.display()
출력:
Preparing namespace for MyClass
Value: 42, Constant: 100
메타클래스로 동적 코드 생성
메타클래스를 활용한 메타프로그래밍은 런타임 중 코드 생성이나 수정을 가능하게 합니다.
예제: 동적 속성·메서드 추가
class MyMeta(type):
def __new__(cls, name, bases, attrs):
print(f"클래스 정의 중: {name}")
# 클래스에 동적 속성 추가
attrs['dynamic_attribute'] = '동적으로 추가됨'
# 클래스에 동적 메서드 추가
def dynamic_method(self):
return f"이것은 {name}을 위해 동적으로 추가된 메서드입니다"
attrs['dynamic_method'] = dynamic_method
return super().__new__(cls, name, bases, attrs)
# 메타클래스 사용 클래스 정의
class MyClass(metaclass=MyMeta):
pass
obj = MyClass()
print(obj.dynamic_attribute)
print(obj.dynamic_method())
출력:
Defining class: MyClass
동적으로 추가됨
이것은 MyClass을 위해 동적으로 추가된 메서드입니다
리플렉션과 메타프로그래밍
메타클래스 메타프로그래밍은 리플렉션을 수반하며, 런타임에 클래스 속성과 메서드를 내성하고 수정할 수 있게 합니다.
예제: 클래스 속성 검사·출력
이 예제에서 `MyMeta` 메타클래스는 `MyClass` 생성 시 속성을 검사하고 출력하며, 메타클래스가 어떻게 동적으로 클래스 정의를 내성·수정할 수 있는지 보여줍니다.
class MyMeta(type):
def __new__(cls, name, bases, dct):
# 클래스 속성 검사 및 출력
print(f"{name} 클래스 속성: {dct}")
return super().__new__(cls, name, bases, dct)
class MyClass(metaclass=MyMeta):
data = "example"
출력:
Class attributes for MyClass: {'__module__': '__main__', '__qualname__': 'MyClass', 'data': 'example'}