2019.05.21 - 클래스 데코레이터를 이용한 데이터 직렬화 (Clean) 코드

def hide_field(field) -> str:
    return "**민감한 정보 삭제"
def show_original(event_field):
    return event_field

class EventSerializer:

    def __init__(self, serialization_fields: dict) -> None:
        self.serialization_fields = serialization_fields

    def serialize(self, event) -> dict:
        return {
            field: transformation(getattr(event, field))
            for field, transformation
            in self.serialization_fields.items()
        }

class Serialization:
    def __init__(self, **transformations):
        self.serializer = EventSerializer(transformations)

    def __call__(self, event_class):
        def serialize_method(event_instance):
            return self.serializer.serialize(event_instance)
        event_class.serialize = serialize_method
        return event_class

@Serialization(
    name=show_original,    password=hide_field
)
@dataclassclass LoginEvent:
    name: str    password: str

일단 EventSerializer는 읽어보면 이해가 되는 코드이므로 pass

Serialization이 데코레이팅 하는 클래스라서 이 친구를 먼저 좀 알아야한다.

일단 초기화 함수에서 가변 키워드 인자를 받는다.
만약 @Serialization이었다면 LoginEvent 클래스를 인자로 받아서 Argument Error가 났을 것이다.

일단은 초기화함수에 대응하는 인자들은 (name=show_original, password=hide_field)가 되겠다.
Serialization 클래스는 초기화가 된 후 LoginEvent 클래스를 데코레이팅한다.

원래 Serialization의 __call__이 호출 되려면 Serialization()()이 되어야 하는데
LoginEvent의 인스턴스를 생성할 때도 저 __call__이 호출된다.

inst = LoginEvent() 는 일반적인 LoginEvent의 인스턴스를 생성하는 것처럼 보이지만
LoginEvent는 데코레이팅 되기 때문에

사실상 Serialization(LoginEvent)()와 같다.
그렇기 때문에 LoginEvent는 serialize라는 메소드를 가진 클래스가 될 수 있고
serialize 메소드를 사용할 수 있다.

댓글

이 블로그의 인기 게시물

로컬 Tomcat 서버 실행속도 개선

2019.05.23 - SQLAlchemy 의 객체 상태 관리 (expire, refresh, flush, commit) 에 관한 이해

2020.02.17 Python의 multiprocessing 중 Pool.map(), chunksize에 관한 내용