본문 바로가기
Python 문법/Python 기본 문법(3.10 기준)

[python3.10 기본] 19. 메타프로그래밍

by cogito21_python 2024. 7. 2.
반응형

19.1 클래스 데코레이터

클래스 데코레이터는 함수 데코레이터와 비슷하게 클래스의 동작을 변경하거나 확장할 수 있습니다.

 

클래스 데코레이터 예제

def add_method(cls):
    def new_method(self):
        print("New method added!")
    cls.new_method = new_method
    return cls

@add_method
class MyClass:
    def __init__(self, name):
        self.name = name

obj = MyClass("example")
obj.new_method()  # New method added!

19.2 메타클래스

메타클래스는 클래스의 클래스입니다. 즉, 클래스의 생성과 동작을 제어할 수 있는 특별한 클래스입니다. type은 파이썬의 기본 메타클래스입니다.

 

메타클래스 정의 및 사용

class MyMeta(type):
    def __new__(cls, name, bases, dct):
        print(f"Creating class {name}")
        return super().__new__(cls, name, bases, dct)

class MyClass(metaclass=MyMeta):
    def __init__(self, value):
        self.value = value

obj = MyClass(10)  # Creating class MyClass

메타클래스를 사용한 클래스 속성 추가

class AttributeAdderMeta(type):
    def __new__(cls, name, bases, dct):
        dct['added_attr'] = "This is an added attribute"
        return super().__new__(cls, name, bases, dct)

class MyClass(metaclass=AttributeAdderMeta):
    pass

obj = MyClass()
print(obj.added_attr)  # This is an added attribute

19.3 동적 속성 및 메소드 추가

파이썬에서는 런타임에 클래스에 속성과 메소드를 동적으로 추가할 수 있습니다.

 

동적 속성 추가

class MyClass:
    def __init__(self, name):
        self.name = name

obj = MyClass("example")
setattr(obj, "age", 30)
print(obj.age)  # 30

동적 메소드 추가

class MyClass:
    def __init__(self, name):
        self.name = name

def new_method(self):
    return f"Hello, {self.name}!"

obj = MyClass("example")
import types
obj.new_method = types.MethodType(new_method, obj)
print(obj.new_method())  # Hello, example!

예제

메타프로그래밍의 다양한 기법을 사용하여 클래스를 생성하고 동작을 변경하는 예제를 보겠습니다.

 

메타클래스를 사용한 싱글톤 패턴 구현

class SingletonMeta(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            instance = super().__call__(*args, **kwargs)
            cls._instances[cls] = instance
        return cls._instances[cls]

class SingletonClass(metaclass=SingletonMeta):
    def __init__(self, value):
        self.value = value

obj1 = SingletonClass(10)
obj2 = SingletonClass(20)
print(obj1 is obj2)  # True
print(obj1.value)  # 10
print(obj2.value)  # 10
반응형