통계 정보를 포함하는 메타클래스를 만들어 클래스의 사용 현황(예: 인스턴스 생성 횟수, 메서드 호출 횟수 등)을 자동으로 추적하는 샘플 코드를 작성해 보았습니다.
from collections import defaultdict
from functools import wraps
class StatsMeta(type):
"""통계 정보를 포함한 메타클래스"""
def __new__(cls, name, bases, dct):
# 통계를 저장할 딕셔너리 추가
dct.setdefault('__stats__', {
'instance_count': 0, # 생성된 인스턴스 수
'method_calls': defaultdict(int), # 메서드 호출 횟수
})
# 메서드를 래핑하여 호출 횟수 추적
for key, value in dct.items():
if callable(value) and not key.startswith("__"):
dct[key] = cls.wrap_method(value, key)
return super().__new__(cls, name, bases, dct)
@staticmethod
def wrap_method(method, method_name):
"""메서드 호출 횟수를 추적하기 위한 래핑 함수"""
@wraps(method)
def wrapped_method(self, *args, **kwargs):
# 호출 횟수 증가
self.__class__.__stats__['method_calls'][method_name] += 1
return method(self, *args, **kwargs)
return wrapped_method
def __call__(cls, *args, **kwargs):
# 인스턴스 생성 횟수 증가
cls.__stats__['instance_count'] += 1
return super().__call__(*args, **kwargs)
def get_stats(cls):
"""현재 클래스의 통계 정보 반환"""
return cls.__stats__
# 통계 정보를 추적하는 데이터 클래스
class DataClass(metaclass=StatsMeta):
def method_a(self):
print("Method A called.")
def method_b(self):
print("Method B called.")
# 사용 예제
if __name__ == "__main__":
# 클래스 인스턴스 생성
obj1 = DataClass()
obj2 = DataClass()
# 메서드 호출
obj1.method_a()
obj2.method_a()
obj1.method_b()
# 통계 정보 출력
stats = DataClass.get_stats()
print(f"Instance Count: {stats['instance_count']}")
print("Method Calls:")
for method, count in stats['method_calls'].items():
print(f" {method}: {count}")
코드 설명
- StatsMeta 메타클래스:
- __stats__: 클래스 수준에서 통계를 저장하는 딕셔너리를 추가.
- wrap_method: 클래스의 메서드를 래핑하여 호출 시 통계 정보를 업데이트.
- __call__: 인스턴스 생성 시 instance_count를 증가.
- get_stats: 통계 정보를 반환하는 클래스 메서드.
- DataClass:
- StatsMeta 메타클래스를 사용하여 메서드 호출 및 인스턴스 생성 통계를 자동으로 관리.
- 사용 예제:
- DataClass 인스턴스를 생성하고 메서드를 호출한 뒤, 통계 정보를 출력.
실행 결과 (예시):
Method A called.
Method A called.
Method B called.
Instance Count: 2
Method Calls:
method_a: 2
method_b: 1
이 메타클래스는 클래스의 동작을 자동으로 감시하고, 개발 및 디버깅 단계에서 클래스의 사용 통계를 확인하는 데 유용합니다.
'실용적인 코드 샘플' 카테고리의 다른 글
[실용적인 코드 샘플] 데이터 카드 패키지 압축 및 해제 (1) | 2025.01.08 |
---|---|
[실용적인 코드 샘플] 메타데이터용 메타클래스 사용 샘플코드 (0) | 2025.01.07 |
[실용적인 코드 샘플] `object` 클래스를 상속 사용자 정의 데이터 타입 (1) | 2024.10.23 |
[실용적인 코드 샘플] 히스토리 기반 통계 작성 클래스 (8) | 2024.10.22 |
[실용적인 코드 샘플] Way Point기반 시나리오 맵 자료구조 (10) | 2024.10.22 |