2021의 게시물 표시

[Rust] 반복자에게 할 일 더해주기 - Iterator adapters

다른 Iterator (a.k.a 반복자)를 받아 새로운 반복자를 반환하는 함수를 iterator adapter 라고 부른다. adapter라는 이름은 GoF의 디자인 패턴 중 하나인 adapter pattern 에서 온 말이라고 한다. 그런데 실제로는 adapter pattern보다는 decorator pattern 에 해당하기 때문에 이름을 신경쓰면 용도를 헷갈릴 수 있다. 그러니 이름에 대해서는 크게 신경 쓰지 않는 것이 좋다. 이름에 대한 불평은 그만하고 iterator adapter가 무엇을 하는가? iterator adapter는 반복자가 순회하면서 할 일을 더해준다. 무슨 말인지는 실제 구현체를 보면 쉽게 이해할 수 있을 것이다. map 함수는 대표적인 adapter다. 함수형 언어를 써본 사람이라면 많이 익숙할 map 함수가 반환하는 반복자는 기존의 값을 새로운 값으로 변환한 값을 순회한다. 이 외에도 표준 라이브러리에 이미 다양한 adapter가 구현돼있다. 이중 가장 많이 사용되는 것은 반복문과 같이 사용하기 좋은 adapter들이다. 조건을 만족하는 값만 돌려주는 filter , 지정 된 몇 개의 값만 반환하는 take , 반대로 몇 개의 값은 생략하고 반환하는 skip , 몇 개씩 값을 건너뛰며 순환하는 step_by 와 같은 adapter가 대표적인 예시다. 이런 adapter를 반복문과 함께 사용하면 복잡한 조건 처리를 쉽게 표현할 수 있다. 이 외에도 영원히 종료하지 않고 순환하게 만드는 cycle 이나, 순환하는 값에는 변환을 주지 않고, 사이드이펙트를 발생시키기만 하는 inspect 도 많이 사용된다. adapter를 사용할 때 주의해야 할 점이 하나 있다. adapter가 반환하는 것 역시 반복자일 뿐이다. 실제로 반복자를 사용하기 전에는 adapter가 지정한 일을 수행하지 않는다. 쉽게 말해 실제로 값이 필요할 때까지 실행을 미루는 lazy evaluation 을 한다는 것이다. 따라서 아래와 같은

[Python] cache 데코레이터로 최적화하기

최적화는 귀찮다. 눈에 띄는 실수를 한 게 아니면 어떻게 고쳐야 할지 감이 오지도 않고, 대부분의 최적화는 가독성을 떨어뜨리기 때문에 버그가 발생할 확률이 늘어난다. 하지만 어떤 최적화 테크닉은 코드를 크게 수정하지 않고 큰 성능 향상을 가져온다. 메모이제이션 이 그 대표적인 예제다. 계산이 무겁거나, 디스크의 값을 읽거나, 네트워크 통신처럼 근본적으로 시간이 오래 걸리는 일은 그 실행 결과를 저장했다 재사용하는 것만으로 큰 성능향상을 가지고 온다. 파이썬은 메모이제이션을 쉽게 적용할 수 있는 데코레이터 를 제공한다. functools 모듈의 lru_cache 데코레이터 가 이것이다. 이 데코레이터를 붙이면 함수의 실행 결과를 캐싱해준다. 캐시의 크기는 maxsize 로 지정할 수 있다. 저장할 실행 값이 이 개수를 넘어가는 경우 LRU 알고리즘 에 따라 가장 오래전에 사용한 결과를 지우고 새 값을 캐싱한다. lru_cache 를 사용하면 쉽게 최적화할 수 있지만 아무 함수에나 사용할 수 있는 건 아니다. 함수의 인자를 캐시키로 사용하기 때문에 함수의 실행 결과가 함수의 인자 이외에 다른 요소에 의존적인 함수에는 사용하지 못한다. 즉, 랜덤 요소가 들어가거나 시간에 따라 결괏값이 변하는 함수에는 사용하면 안 된다. 결정성이 보장되는 함수에만 사용할 수 있다는 것은 모든 캐시의 공통적인 특성이다. 여기에 더해 파이썬이 제공하는 lru_cache 는 그 구현상의 문제로 한 가지 제약이 더 있다. 이 데코레이터는 값을 저장하기 위해 인자를 키로 가지는 dictionary 를 사용한다. 따라서 모든 인자가 hashable 타입이어야 한다. 다시 말해 mutable 하지 않은 dictionary , set , list 등을 인자로 받는 함수는 이 데코레이터를 사용해 캐싱할 수 없다. 이런 타입을 인자로 받던 함수는 그 인자를 frozenset 이나 tuple 같은 immutable 타입으로 변환해야 한다. 게다가 keyword argumen