Skip to content

KR_MetaProgramming

somaz edited this page Mar 6, 2025 · 5 revisions

파이썬 메타프로그래밍

1. 메타클래스 기초

메타클래스는 클래스의 생성을 제어하는 "클래스의 클래스"이다.

# 기본 메타클래스
class MyMetaclass(type):
    def __new__(cls, name, bases, attrs):
        # 클래스 속성 수정
        attrs['custom_attribute'] = 'Added by metaclass'
        return super().__new__(cls, name, bases, attrs)

class MyClass(metaclass=MyMetaclass):
    pass

print(MyClass.custom_attribute)  # 'Added by metaclass'

2. 데코레이터와 메타클래스

# 클래스 데코레이터
def add_methods(cls):
    def new_method(self):
        return "This is a new method"
    
    cls.new_method = new_method
    return cls

@add_methods
class MyClass:
    pass

obj = MyClass()
print(obj.new_method())  # "This is a new method"

3. 속성 접근 제어

class ValidString(type):
    def __new__(cls, name, bases, attrs):
        # 문자열 속성 검증
        for key, value in attrs.items():
            if isinstance(value, str):
                attrs[key] = value.strip()
        return super().__new__(cls, name, bases, attrs)

class MyClass(metaclass=ValidString):
    name = "  John Doe  "
    title = "  Developer  "

print(MyClass.name)   # "John Doe"
print(MyClass.title)  # "Developer"

4. 동적 클래스 생성

# 동적으로 클래스 생성
def create_model_class(name, fields):
    def __init__(self, **kwargs):
        for field in fields:
            setattr(self, field, kwargs.get(field))
    
    return type(name, (), {
        '__init__': __init__,
        'fields': fields
    })

# 사용 예시
UserModel = create_model_class('User', ['name', 'email', 'age'])
user = UserModel(name='John', email='john@example.com', age=30)

5. 속성 디스크립터

class ValidatedField:
    def __init__(self, validation_func):
        self.validation_func = validation_func
        self.name = None

    def __get__(self, instance, owner):
        if instance is None:
            return self
        return instance.__dict__.get(self.name)

    def __set__(self, instance, value):
        if not self.validation_func(value):
            raise ValueError(f"Invalid value for {self.name}")
        instance.__dict__[self.name] = value

    def __set_name__(self, owner, name):
        self.name = name

class User:
    name = ValidatedField(lambda x: isinstance(x, str) and len(x) >= 2)
    age = ValidatedField(lambda x: isinstance(x, int) and 0 <= x <= 150)

6. 실용적인 예제

ORM 스타일 모델 정의

class ModelMetaclass(type):
    def __new__(cls, name, bases, attrs):
        fields = {}
        for key, value in attrs.items():
            if isinstance(value, Field):
                fields[key] = value
        
        attrs['_fields'] = fields
        return super().__new__(cls, name, bases, attrs)

class Field:
    def __init__(self, field_type):
        self.field_type = field_type

class Model(metaclass=ModelMetaclass):
    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

class User(Model):
    name = Field(str)
    age = Field(int)
    email = Field(str)

싱글톤 패턴

class Singleton(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=Singleton):
    def __init__(self):
        self.connection = "Connected"

주요 팁

  • 메타클래스는 신중하게 사용
  • 가독성을 고려한 설계
  • 문서화 철저히 하기
  • 디버깅 고려
  • 표준 라이브러리 패턴 참고

Clone this wiki locally