[Fluent Python] 10장 시퀀스 해킹, 해시, 슬라이스

10장 시퀀스 해킹, 해시, 슬라이스

벡터 공간 모델은 주로 정보 검색 분야에서 이용되며, 핵심 연관성 척도는 코사인 유사도이다. 실제 벡터 연산을 위해서는 NumPy와 SciPy 패키지가 유용하다. gensim PyPI은 이 둘을 이용하여 자연어 처리 및 정보 검색을 위한 벡터 공간 모델링을 보여준다.

사용자 정의형 Vector2D 예제

__repr__()는 디버깅 시에 시스템에서 호출하므로, 결코 예외를 발생시키면 안된다.

프로토콜과 덕 타이핑

파이썬에서 완전히 작동하는 시퀀스형을 구현하기 위해서 특별한 클래스를 상속할 필요가 없다. 단지 시퀀스 프로토콜이 필요로 하는 메서드만 구현하면 된다. 시퀀스형임을 선언하지 않았음에도 시퀀스처럼 동작하기 때문에 시퀀스인 것이다. 이러한 메커니즘에 대해 알렉스 마르텔리는 덕 타이핑이라고 정의하였다.

프로토콜은 비공식적이며, 강제로 적용되는 개념이 아니므로, 특정 환경에 따라 필요한 메서드만 구현하여 쓰면 된다.

덕 타이핑

그것이 오리인지 조사하지 말라.

오리 같은 행동의 정확히 어떤 부분을 언어로 표현해야 하는지에 따라 오리처럼 꽥꽥거리는지, 오리처럼 뒤뚱뒤뚱 걷는지 등을 조사하라.

by 알렉스 마르텔리 (2000.07.26, comp.lang.python 뉴스그룹)

슬라이스 가능한 벡터 구현

__len()____getitem__()를 구현하면 참조와 슬라이스가 기능한다(제대로 동작하는 건 아니다).

슬라이스의 작동방식

슬라이스에서 1:4와 같은 표현식은 slice(1, 4, None)이 된다.

slice객체의 indices라는 메서드는 생략되거나 음수인 인덱스를 주어진 시퀀스에 맞게 맞추어주는 역할을 한다.

슬라이스를 인식하는 __getitem__()

인자로 넘어오는 인덱스의 타입에 따라서 작동 방식을 달리 지정해줘야 한다.

동적 속성 접근을 구현한 벡터 예제

속성을 찾지 못하면, 인터프리터는 __getattr__() 메서드를 호출한다. 다시 말해, 파이썬은 객체의 속성이 찾고, 해당 속성이 없는 경우 객체의 클래스에서 검색하고, 상속 트리를 따라 계속 올라가면서 검색한다. 그래도 찾지 못하면 self와 속성명을 인자로 하는 __getattr__() 메서드를 호출한다.

이 특성 때문에, __getattr__() 메서드를 구현할 때는 __setattr__() 메서드도 함께 구현해야 한다. 그렇지 않은 경우, 사용자가 새로운 값을 속성값으로 지정하면, 그 값은 객체 내에 새로운 속성을 만들고, 다시는 __getattr__() 메서드에 도달하지 않는다.

해싱과 더 빠른 ==

일반적으로 객체의 각 속성마다 해시값을 구한다음 배타적 비트 연산자(xor, ^)를 이용하여 객체의 해싱 값을 구한다.

이 때, functools.reduce()가 유용하게 이용될 수 있다. 비트 연산자는 operator.xor로 참조 가능하다.

임의의 길이를 갖는 벡터의 값을 비교하기 위해서는 먼저 길이가 동일한지 검사하고, zip()를 이용하여 1:1 비교가 가능하다.

zip()은 가장 짧은 시퀀스에 맞춰서 쌍을 맞춰주는데, zipper가 잠기는 건 연상하면 쉽다. fillvalue 파라미터를 이용하여 가장 긴 리스트에 맞출 수도 있다.

포맷팅을 구현한 벡터

__format__()함수를 이용하여 포맷을 지정할 수 있는데, 기존에 사용하는 코드는 피하는 것이 좋다. 실수형 포멧 코드로는 eEfFgGn%가 있고, 정수형은 bcdoxXn, 문자열은 s를 쓰고 있다.

요약

슬라이스 표현식은 슬라이스 객체를 만들고, __getitem__()에서 처리한다. __getattr__()는 반드시 __setattr__()와 같이 써줘야 하며, __hash__() 메서드를 살펴보면서, functools.reduce()도 살펴보았다.

읽을거리

reduce() 고위함수는 다른언어에서 fold(), accumulate(), aggregate(), compress(), inject() 등의 함수로 제공된다. 함수형 프로그래밍에 중점을 둔 고위함수 응용방법은 “Fold (higer-order function)” 문서를 참조하자.