프로그래밍 분야에서 동적 계획법의 핵심이 되는 기술로 메모이제이션(memoization)이 있습니다. 이전에 계산한 값을 메모리에 저장함으로써, 동일한 계산의 반복 수행을 제거하여 프로그램 실행 속도를 빠르게 하는 기술입니다. 단적으로 말하면, 동일한 input에 대해 동일한 output이 나오는 함수지만 실행 비용이 비싼 경우 메모이제이션을 적용할 수 있습니다.

메모이제이션 구현하기

@memoize라는 간단한 메모이제이션 데코레이터를 구현해 보도록 합시다.

인자들을 stringify하여 cache 딕셔너리에 들어 있는지 검사하고, 들어 있지 않다면 함수의 실행 결과를 저장하여 나중에 똑같은 인자를 통해 해당 함수를 다시 호출했을 때 cache 딕셔너리에 저장된 값을 즉시 반환합니다. 따라서 memoize 데코레이터가 붙어 있는 expensive_fn 함수를 처음 실행했을 때는 3초가 걸렸지만, 똑같은 인자로 두 번째 실행했을 때는 매우 빠른 속도로 결과 값을 얻어낼 수 있습니다.

functools.lru_cache

Python 3.2 이상에서는 빌트인 모듈인 functoolslru_cache 데코레이터를 사용해서 함수의 반환값들을 메모이제이션할 수 있습니다.

'Python 계열 > Python 레거시 글' 카테고리의 다른 글

[Python] zip  (0) 2018.07.28
[Python] Coroutines  (0) 2018.07.27
[Python] Assert  (0) 2018.07.25
[Python] Generator  (0) 2018.07.23
[Python] Iterable, Sequence, Iterator  (0) 2018.07.22

assert라는 개념은 가정 설정문을 뜻하는 assertion에서 나오게 되었습니다. 프로그램 개발의 과정에서 '실수는 일어난다'고 가정하고, 참/거짓을 미리 가정하는 문을 배치하여 이를 방지하는 것입니다. 이것을 방어적 프로그래밍(defensive programming)이라고 부르며, 방어적 프로그래밍의 가장 일반적인 구현 방식은 여기서 말한 assert를 사용합니다.

assert

assert(가정 설정문)은 단순하게 프로그램의 특정 지점에서 항상 참이어야 하는 문장입니다. Python을 비롯해 assertion을 지원하는 프로그래밍 언어들은 대부분 assert의 조건을 확인하여 참이면 다음 문장으로 넘어가고, 거짓이면 프로그램을 정지시킵니다. Python에서는 assert의 조건이 거짓인 경우 AssertionError를 발생시킵니다. assert의 예는 다음과 같습니다.

assert [condition] 형태입니다. 조금 현실적으로 바꾼다면, 아래처럼 작성할 수 있습니다.

assert에 메시지를 작성할 수도 있습니다. assert [condition], [message] 형태입니다.

이는 raise AssertionError('Data should only contain positive values')와 같은 결과를 내보냅니다.

'Python 계열 > Python 레거시 글' 카테고리의 다른 글

[Python] Coroutines  (0) 2018.07.27
[Python] memoize  (0) 2018.07.26
[Python] Generator  (0) 2018.07.23
[Python] Iterable, Sequence, Iterator  (0) 2018.07.22
[Python] Decorator  (0) 2018.07.21

Generator는 iterator의 역할을 할 수 있는 generator 객체를 만들기 위한 함수입니다. 쉽게 말하면 iterator를 생성해 주는 함수입니다.(매직 메소드인 __next__()가 정의되어 있으므로) 다만 return 문을 통해 특정 값을 반환하고 호출 스택에서 제거되어 종료되는 일반적인 함수와 다르게, generator는 yield를 만나면 함수가 정지되며, next()가 호출될 때마다 하나의 값만을 반환하게 됩니다. 따라서 일반적인 iterator에 비해 아주 작은 메모리만을 사용합니다. 이를 프로그래밍 분야에서는 '게으른 연산'이라고 부릅니다.

Generator 함수

List의 모든 값을 제곱하여 반환하는 함수를 작성해 보겠습니다.

위의 square_numbers는 우리가 지금까지 봐왔던 일반적인 함수입니다. 한 번의 호출에 한 번의 반환을 하고, 그대로 함수는 종료됩니다.

아래의 square_numbers_generatorreturn 대신 yield라는 키워드를 통해 값을 반환하는 함수입니다. yield 구문은 해당 함수의 반환값에 대해 next()가 호출될 때마다 한 번씩 실행되며, 따라서 iterator와 거의 동일하게 동작합니다. 빌트인 함수 dir()을 이용해 객체에 담겨 있는 필드와 메소드를 확인해 보면, __next__() 메소드가 정의되어 있는 것도 확인할 수 있습니다.

Generator expression

위에서 함수 형태로 선언했던 generator 표현을 조금 더 쉽게 할 수 있도록, Python에서는 generator expression을 제공합니다. List comprehension의 대괄호를 소괄호로 바꾸기만 하면 됩니다.

'Python 계열 > Python 레거시 글' 카테고리의 다른 글

[Python] memoize  (0) 2018.07.26
[Python] Assert  (0) 2018.07.25
[Python] Iterable, Sequence, Iterator  (0) 2018.07.22
[Python] Decorator  (0) 2018.07.21
[Python] Closure  (0) 2018.07.20

+ Recent posts