Vector 버전 #:2 슬라이스 가능한 시퀀스

매일 공부(ML)·2023년 1월 19일
0

Fluent Python

목록 보기
68/130

객체지향 상용구

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

Vector 버전 #:2 슬라이스 가능한 시퀀스

FrenchDeck 예제에서 self._components를 사용한 것처럼 객체 안에 들어있는 시퀀스 속성에 위임하면 시퀀스 프로토콜을 구현하기 위한 len()과 getitem()메서드를 구현할 수 있다.

class Vector:
	#중략
    #...
    
    def __len__(self):
    	return len(self._components)
    
    def __getitem__(self, index):
    	return self._components[index]

내장된 시퀀스형은 슬라이싱 했을 때 다른 자료헝이 아니라 자신과 동일한 자료형의 객체를 생성하고 Vector를 슬라이싱해서 Vector객체를 생성하려면, 슬라이싱 연산을 배열에 위임하면 안되고 getitem() 메서드가 받은 인수를 분석해서 제대로 처리해야 한다.


슬라이싱의 작동방식

#__getitem__()과 slice()의 동작 확인

class MySeq:
	def __getitem__(self, index):
    	return index
        
s = MySeq()
#slice 클래스의 속성 조사
slice
dir(slice)

dir(slice)를 호출하면 indices라는 흥미로운 메서드가 보이고, help(slice.indices)명령을 실행하면 된다.

"""
S.indices(len) -> (start, stop, stride)
길이가 len인 시퀀스 S가 나타내는 확장된 슬라이스의 start와 stop인덱스 및 stride 길이를 계산하여 경계를 벗어난 인덱스는 일반적인 슬라이스를 처리하는 방법과 동일하게 잘라낸다.
"""

고로, indices는 "빠지거나 음수인 인덱스" 그리고 "대상 시퀀스보다 긴 슬라이스'를 우아하게 처리하는 내장된 시퀀스에 구현된 복잡한 논리를 보여주고, 이 메서드는 주어진 길이의 시퀀스 경계 안에 들어가도록 조정된 0이나 양수인 start, stop, stride로 구성된 정규화된 튜플을 생성한다.


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

len()과 getitem()이 슬라이싱을 제대로 처리하도록 구현

#vector_v2.py의 일부

def __len__(self):
	return len(self._components)
    
def __getitem__(self, index):
	cls = type(self)
    if isinstance(index, slice):
    	return cls(self._components[index])
    elif isinstance(index, numbers.Integral):
    	return self._components[index]
        
    else:
    	msg = '{cls.__name__} indices must be integers'
        raise TypeError(msg.format(cls=cls))

"""
getitem()의 else문에서 어떤 예외가 발생했는지 알아내기 위해서 대화형 콘솔을 이용해서 문장의 결과를 확인하고 파이썬 에선 TypeError를 발생시키며, 인덱스는 정수형이어야한다는 에러 메시지를 출력한다.

즉, 파이썬스러운 객체를 만들려면 파이썬의 객체를 흉내내야 한다.
"""

#Vector.getitem()의 테스트

v7 =Vector(range(7))
profile
성장을 도울 아카이빙 블로그

0개의 댓글