파이썬으로 Reactivity 따라하기

Reading time ~2 minutes

JavaScript의 Vue, React 등에서 쓰이는 Reactivity 개념을 간단하게 구현해보는 The Best Explanation of JavaScript Reactivity 🎆라는 게시글을 보고 파이썬으로 따라 구현해봤다.

Vue updates

JavaScript

아래 코드사진은 원문에서 가져왔다. target 전역변수를 사용하고 Object.defineProerty로 등록된 Depwatcher 함수를 이용해 값 변동을 추적하고 등록된 함수를 실행한다.

JavaScript code

Python

JavaScript 코드에 가깝게 파이썬 코드를 작성했다. 다만 Object.defineProperty에 대응되는 기능을 구현하기 위해 임의로 Data 클래스에 __setattr__, __getattribute__를 구현하다보니 코드가 장황해졌다. data를 dict로 만들고 __getitem__, __setitem__을 오버라이딩 하는 방법도 고려했으나 data['price']가 아닌 data.price 문법을 유지하고 싶어 클래스로 선언했다.

원문 코드에선 data의 프로퍼티를 순회하면서 dep을 만들어 주었는데 파이썬 코드에선 이를위해 deps 변수를 활용했다.

# main.py
class Dep:
    def __init__(self):
        self.subscribers = []

    def depend(self):
        if target and target not in self.subscribers:
            self.subscribers.append(target)

    def notify(self):
        for sub in self.subscribers:
            sub()


class Data:
    def __init__(self, *args, **kwargs):
        for name in kwargs:
            setattr(self, name, kwargs[name])

    def __setattr__(self, name, value):
        if name not in deps:
            deps[name] = Dep()
        result = super().__setattr__(name, value)
        deps[name].notify()
        return result

    def __getattribute__(self, name):
        deps[name].depend()
        value = super().__getattribute__(name)
        return value


deps = {}
data = Data(price=5, quantity=2)
target = None


def watcher(func):
    global target
    target = func
    target()
    target = None


def total_func():
    data.total = data.price * data.quantity


def sale_price_func():
    data.sale_price = data.price * 0.9


watcher(total_func)
watcher(sale_price_func)


def print_data():
    attrs = ('sale_price', 'price', 'quantity', 'total')
    s = (f'{attr}: {getattr(data, attr)}' for attr in attrs)
    print(', '.join(s))


if __name__ == '__main__':
    print_data()
    data.price = 20
    print_data()
    data.quantity = 3
    print_data()

위의 코드를 실행하면 다음과 같은 결과를 확인할 수 있다.

$ python main.py
sale_price: 4.5, price: 5, quantity: 2, total: 10
sale_price: 18.0, price: 20, quantity: 2, total: 40
sale_price: 18.0, price: 20, quantity: 3, total: 60

마무리

전역 변수를 활용한다는게 썩 마음에 들진 않는다. 파이썬의 Lambda 함수에선 대입문을 사용할 수 없다보니 Arrow function을 사용한 JavaScript 처럼 깔끔한 코드가 나오지도 않았다. 다만 callback 함수를 어떻게 등록하고 어떤 원리를 통해 자동으로 업데이트 되는지 알아보기엔 적당한 코드였다.

하시코프 한국 사용자 모임 밋업 정리

HashiCorp 한국 사용자 모임이 주최하여 2018년 7월 28일 공개SW개발자센터 대강의장에서 있었던 하시코프 한국 사용자 모임 밋업 내용을 정리했다.밋업소개 HashiCorp korea user group 소개 HashiCorp kor...… Continue reading

python script.py에서 벗어나기

Published on June 30, 2018